【发布时间】:2013-11-21 11:15:52
【问题描述】:
我有一个具有自反关联的 ActiveRecord 类(注意:出于保密原因,类名已编辑):
class Thing < ActiveRecord::Base
belongs_to :parent,
class_name: 'Thing'
has_many :children,
class_name: 'Thing',
foreign_key: :parent_id
scope :children, ->{ where(arel_table[:parent_id].not_eq(nil)) }
end
我想让所有的孩子,左外连接到他们的父母,如果它存在的话,对父母有一个额外的条件,同时仍然急切地加载父母。
通常在这种情况下,我会做类似的事情:
Thing.includes(:other_thing).merge(OtherThing.some_scope)
但在这种情况下是不可能的:因为这是一个自联接,如果我从 Thing 合并一个范围,则条件将适用于子事物,而不是父母。
我尝试在原始 SQL 中执行此操作:
scope :some_scope, ->{
children.joins(<<-SQL).references(:parent)
LEFT OUTER JOIN things AS parents
ON things.parent_id = parents.id
AND parents.some_field IN ('foo', 'bar')
SQL
}
查询没问题,但似乎父级没有得到预先加载(在此范围内尝试 map(&:parent) 时有 n+1 个查询)。
目前,我或多或少的工作解决方案是使用子查询(采摘与父条件匹配的 id,然后选择具有parent_id IN 这个集合的子查询),但我想知道是否有一个更合适/优雅的。
【问题讨论】:
标签: mysql sql ruby-on-rails activerecord ruby-on-rails-4