如何为多个关联进行急切加载?

时间:2014-11-05 10:05:55

标签: ruby-on-rails ruby-on-rails-4 query-optimization eager-loading public-activity

我正在使用public_activity以及我的一个部分内容:

<%= link_to "#{activity.trackable.user.name} " + "commented on " + "#{activity.trackable.node.name}", node_path(activity.trackable.node.family_tree_id,activity.trackable.node) %>

这是通过这个电话执行的:

      <% @unread_act.each do |friend| %>
        <li><%= render_activity friend %> </li>
      <% end %>

该实例变量在我的ApplicationController中分配:

  before_filter :handle_nofications

  def handle_nofications
    if current_user.present?
      @unread_act = Notification.where(owner_id: current_user).includes(:trackable => :user).unread_by(current_user)
    end
  end

我正在使用gem Bullet,找到N + 1个查询,我得到的反馈是:

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

我最初收到的信息是:trackable:user。我现在都渴望通过includes在该赋值语句中加载。

然而,我不知道如何在热切的加载中深入3级 - 而不是仅仅两次。

鉴于节点被调用为activity.trackable.node.name,我想一些适当的预先加载分配看起来像:

  @unread_act = Notification.where(owner_id: current_user).includes(:trackable => [:user, :node]).unread_by(current_user)

但我得到的错误是:

ActiveRecord::AssociationNotFoundError at /
Association named 'node' was not found on Node; perhaps you misspelled it?

当我这么做时,我甚至会这样做:

@unread_act = Notification.where(owner_id: current_user).includes(:trackable => :node).unread_by(current_user)

所以我怀疑其他地方出了问题。

有什么想法吗?

修改1

参见Node&amp;下面的通知模型和协会。

Node.rb

class Node < ActiveRecord::Base
  include PublicActivity::Model
  tracked except: :update, owner: ->(controller, model) { controller && controller.current_user }

  belongs_to :family_tree
  belongs_to :user
  belongs_to :media, polymorphic: true, dependent: :destroy
  has_many :comments, dependent: :destroy
  has_many :node_comments, dependent: :destroy

Notification.rb

class Notification < PublicActivity::Activity
  acts_as_readable :on => :created_at
end

2 个答案:

答案 0 :(得分:1)

希望在rails 5.0中修复此问题。已存在问题和拉取请求。

https://github.com/rails/rails/pull/17479

https://github.com/rails/rails/issues/8005

我有分叉导轨并将贴片应用到4.2稳定版本,它对我来说很有用。尽管我不能保证定期与上游同步,但请随意使用它。

https://github.com/ttosch/rails/tree/4-2-stable

答案 1 :(得分:0)

似乎正确的方法是在trackable属性上使用数组,如下所示:

@unread_act = Notification.where(recipient_id: current_user).includes(:trackable => [:user, :node]).unread_by(current_user).order("created_at desc")

主要部分是:

includes(:trackable => [:user, :node])

这似乎很有效。