如何在1次呼叫中急切加载两级关联?

时间:2014-10-29 08:07:24

标签: ruby-on-rails ruby-on-rails-4 eager-loading

我有FamilyTree, Node, Comment, & User个型号。

这种关系是这样的:

FamilyTree

class FamilyTree < ActiveRecord::Base
  belongs_to :user
  has_many :memberships, dependent: :destroy
  has_many :members, through: :memberships, source: :user, dependent: :destroy
  has_many :nodes, dependent: :destroy
end

Node

class Node < ActiveRecord::Base
  belongs_to :family_tree
  belongs_to :user
  has_many :comments, dependent: :destroy
end

Comment

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :node
end

User

class User < ActiveRecord::Base
  has_one :family_tree, dependent: :destroy
  has_many :memberships, dependent: :destroy
  has_many :nodes, dependent: :destroy
  has_many :comments
end

Membership ## This is just to store the user memberships on various family_trees

class Membership < ActiveRecord::Base
  belongs_to :family_tree
  belongs_to :user      
end

在我使用此版本的Dashboard#IndexController中,我有:

  def index
    @family_tree = current_user.family_tree
    @nodes = @family_tree.nodes.includes(:comments)
    @node = current_user.nodes.new
    @memberships = current_user.memberships.limit(3)    
  end

当我尝试使用Bullet gem优化我的应用时,我收到此消息:

N+1 Query detected
  Comment => [:user]
  Add to your finder: :include => [:user]
N+1 Query method call stack

我的_comments部分产生此N + 1问题的方式如下所示 - 在我的views/dashboard/index.html.erb中:

      <% @nodes.each do |node| %>
          <%= render partial: "shared/comments", locals: {node: node} %>
      <% end %> <!-- node -->

这是我的_comments部分中围绕这些行发生n + 1个违规查询的地方。

<% node.comments.each do |comment| %>
     <li class="clearfix">
         <a class="avatar" href="#">
             <%= image_tag(comment.user.avatar.url)%>

所以似乎解决方案是优化我的控制器调用,但我不太确定如何进行2级关联。我试过这个:

@nodes = @family_tree.nodes.includes(:comments).includes(:user)

但这似乎没有摆脱N + 1查询问题。

有什么想法吗?

1 个答案:

答案 0 :(得分:7)

您必须将哈希值传递给includes

@nodes = @family_tree.nodes.includes(:comments => :user)