【问题标题】:How do I do eager loading for multiple associations?如何为多个关联进行预加载?
【发布时间】:2014-11-05 10:05:55
【问题描述】:

我正在使用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.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

【问题讨论】:

  • 展示你的模型。 Notificationtrackable 关联是什么? Node 的关联是什么?
  • @MarekLipka 更新问题。

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


【解决方案1】:

这有望在 rails 5.0 中得到修复。已经有一个问题和一个拉取请求。

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

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

我已经分叉了导轨并将补丁应用于 4.2-stable,它对我来说非常有用。随意使用它,即使我不能保证定期与上游同步。

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

【讨论】:

    【解决方案2】:

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

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

    主要部分是:

    includes(:trackable =&gt; [:user, :node])

    这似乎效果很好。

    【讨论】:

      猜你喜欢
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多