请注意,这不是关于向关联添加WHERE条件的问题,而是关于在使用eager_load时如何更改JOIN子句的相当高级的问题。
假设我有这些模型
class Parent
has_many :children
have_many :grades, through: :children
end
class Child
belongs_to :parent
end
class Grade
belongs_to :child
end
所以要急切地加载我会做的父母:
Parent.eager_load(:grades)
但是,如果我想要所有的父母 - 但只是急切地加载最高得分如此:
LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'
我尝试过使用includes(:children).joins("LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'")
,但由于Rails没有构建关联对象,因此会为每个父对象产生额外的查询。
我没有找到任何关于将eager_load
与自定义SQL字符串一起使用的引用,并且dug through the source没有得到任何更明智的提示。
答案 0 :(得分:1)
这并不能解决所述问题。
您无法通过调用eager_load
来改变生成的JOIN。 WHERE子句是您唯一的选项,它与JOIN上的条件具有完全相同的效果。就在这里,即使你不想要它:
Parent.eager_load(:grades).where("grades.level = 'A+'")
答案 1 :(得分:1)
如果我是对的,你只想急切加载关联的子集。好吧,为了做到这一点,你需要超越铁轨。您基本上可以创建另一个关联,例如" highest_grade"使用ruby lambda中的where子句获取等级A +的等级。这可以通过使用以下代码片段来实现
class Parent
has_many :children
has_many :grades, through: :children
has_many :highest_grade, ->{where(level: 'A+')}, class_name: "Grade", through: :children
end
现在您需要急切加载highest_grade关联。
Parent.eager_load(:highest_grades)
这将基本上加载所有父母以及只有等级为A +的成绩。
它会生成以下查询。
SQL (0.3ms) SELECT `parents`.`id` AS t0_r0, `parents`.`created_at` AS t0_r1, `parents`.`updated_at` AS t0_r2, `grades`.`id` AS t1_r0, `grades`.`child_id` AS t1_r1, `grades`.`created_at` AS t1_r2, `grades`.`updated_at` AS t1_r3, `grades`.`level` AS t1_r4 FROM `parents` LEFT OUTER JOIN `children` ON `children`.`parent_id` = `parents`.`id` LEFT OUTER JOIN `grades` ON `grades`.`child_id` = `children`.`id` AND `grades`.`level` = '
如果您想了解这是如何工作的。请使用this link as a reference