Rails have activerecord grab all needed associations in one go?

China☆狼群 提交于 2019-12-24 09:28:00

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!