How do I eager load two levels of associations in

2019-08-30 23:18发布

问题:

I have FamilyTree, Node, Comment, & User models.

The relationship is like this:

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

In my Dashboard#IndexController where I am using this, I have:

  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

When I am trying to optimize my app with the Bullet gem, I get this message:

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

My _comments partial that is generating this N+1 issue is called like this - in my views/dashboard/index.html.erb:

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

This is where the n+1 offending queries occur, around these lines in my _comments partial.

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

So it seems the solution is to optimize my controller call, but I am not quite sure how to do 2-levels of association. I tried this:

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

But that doesn't seem to get rid of the N+1 query problem.

Any ideas?

回答1:

You have to pass a hash to the includes

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