w3d4 Flashcards
What do ActiveRecord querying methods return?
An instance of ActiveRecord::Relation
When are Relation instances evaluated (i.e. a database query is fired)?
When they are directly accessed (i.e. via #each)
What happens to a Relation after a query is run?
After the query is run, the results are cached by Relation; they are stored for later re-use. Subsequent calls to each will not fire a query; they will instead use the prior result.
Say we want to re-fire a query after changing something in the db. What do we do?
Reload and ignore cached values by calling #query_method(true) on the instance in question.
What happens when we call ::where on a Relation?
A new Relation object is returned that reflects the query (note, however, that it is the existing relation that is queried, not the db. Furthermore, the already existing relation remains unchanged.)
What does #where_values do when called by a Relation?
It returns the results of the previous where query as a hash.
What happens when a method like #count is called on a Relation?
It forces the evaluation of a query, unlike most other query methods.
How can we force the evaluation of a query?
With #load.
How do we prefetch an association, and why bother?
By using
self.table_name.includes(:association_name)
This allows us the fire off the query based on the defined association, and avoids overhead by needing to run the query later.
What does prefetching association allow us to do?
Use iterative (N+1) methods on the prefetched data without the normal SQL query overhead.
For example, if we do the following:
comments = user.comments.includes(:post, :parent_comment)
Then all of the following will work without hitting the db:
comments[0].post
comments[0].parent_comment
comments.each do |comment|
How can we do a nested prefetch (for multi-level associations?)
posts = user.posts.includes(:comments => [:author, :parent_comment])
What does ::joins require?
An association given as a symbol argument.
What does ::joins return, and how is this different from what ::includes returns?
joins
does the opposite of includes
:
# includes
fetches the entries and the associated entries
both. User.joins(:comments)
returns no Comment
data, just
the User
columns. For this reason, joins
is used less
commonly than includes
.
What SQL operation does ::joins perform?
INNER JOIN
When should we use ::joins as opposed to ::includes?
When we want to do an aggregation (i.e. count), as opposed to a retrieval of all column values.
So, what is going on here?
posts_with_counts = self
.posts
.select(“posts., COUNT() AS comments_count”) # more in a sec
.joins(:comments)
.group(“posts.id”) # “comments.post_id” would be equivalent
We are creating an array of Post objects, but Rails is also able to dynamically add a new method to the returned Post objects, #comments_count, which stores the results of the SELECT clause which is also specified. Cool!
What is going on here?
posts_with_counts = self
.posts
.select(“posts.*, COUNT(comments.id) AS comments_count”) # more in a sec
.joins(“LEFT OUTER JOIN comments ON posts.id = comments.post_id”)
.group(“posts.id”) # “comments.post_id” would be equivalent
We are performing a non-default LEFT OUTER JOIN to include posts with zero comments. Once again, Rails dynamically adds #comments_count to the returned Post objects.
What is going on here?
start_time = (DateTime.now.midnight - 1.day) end_time = DateTime.now.midnight Comment.joins(:posts).where( 'posts.created_at BETWEEN ? AND ?', start_time, end_time ).uniq
We are interpolating values into the where query to retrieve the unique posts from the previous day.
What is a scope?
An ActiveRecord::Base class method which returns a relation.
What is a dynamic finder and how do we use one?
Rails can figure out what to look for by making a method that builds on find_by
Application.find_by_email_address(“ned@appacademy.io”)
How can we retrieve records in order?
Client.order(“orders_count ASC, created_at DESC”).all
How can we use GROUP BY and HAVING clauses?
UserPost
.joins(:likes)
.group(“posts.id”)
.having(“COUNT(*) > 5”)
How can we use our own SQL queries to access the db directly?
Use ::find_by_sql(«-SQL). This takes the standard heredoc format.
When should we go into the db directly with ::find_by_sql ?
When our queries grow to a complexity that it becomes too much of a hassle to figure out in AR. AR is meant to ease your burden on easy queries, not add to it.
How do we use ::find_by_sql with interpolated values?
Pass the arguments AND the query in an array:
Post.find_by_sql( [ "SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date ] )
What does ::find_by_sql return?
An array of objects.