简体   繁体   中英

Rails have activerecord grab all needed associations in one go?

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).

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)

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.

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) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM