问题
I have a model Comment, which has_a User.
In my display page, I am doing a Comment.all, and then displaying each comment.
In the view I need to display not only the comment, but also information about the associated user (ie the author).
<% @comments.each do |comment| %>
<%= comment.user.name %>
<%= comment.user.email %>
...etc...
<% end %>
This is fine and all, but activerecord translates this into one SELECT * FROM users WHERE USER.id = commentId query per EACH comment I have.
This is a little ridiculous, especially on a page with hundreds of comments. (That's hundreds of individual separate DB hits!)
When I am doing the Comment.all, is there away to tell rails to not only grab the comments, but also grab the associated users, and then when I call comment.user.blah later, for it to not grab it from db again? (This way it would do it all in one db statement).
回答1:
You should use .includes.
From the doc:
Solution to N + 1 queries problem
Active Record lets you specify in advance all the associations that are going to be loaded. This is possible by specifying the includes method of the Model.find call. With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
Revisiting the above case, we could rewrite Client.all to use eager load addresses:
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
Or, in your case, it would be
Comment.includes(:user)
回答2:
You can do this easily with ActiveRecord, you just need to use the eager loading feature in it. So Comment.all(:include => :user) will run one large query rather than one query per record.
回答3:
Checkout http://stackoverflow.com/questions/29908230/rails-have-activerecord-grab-more-than-one-association-in-one-go/29908317#29908317 if you want to associate with more than one association in the includes statement.
The gist is using Comment.includes(:user, :dates, :whatevertableetc).
来源:https://stackoverflow.com/questions/8722632/rails-have-activerecord-grab-all-needed-associations-in-one-go