max*_*max 3 activerecord ruby-on-rails ruby-on-rails-4
请注意,这不是一个关于向关联添加 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
Run Code Online (Sandbox Code Playgroud)
因此,为了急切地加载父母,我会这样做:
Parent.eager_load(:grades)
Run Code Online (Sandbox Code Playgroud)
但如果我想要所有的父母 - 但只是渴望加载最高分,如下所示:
LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'
Run Code Online (Sandbox Code Playgroud)
我尝试过使用includes(:children).joins("LEFT OUTER JOIN grades ON grades.child_id = children.id AND grades.level = 'A+'"),但由于 Rails 不构建关联对象,因此会导致对每个父级进行额外的查询。
我还没有找到任何关于使用eager_load自定义 SQL 字符串的参考资料,并且已经深入研究了源代码,但没有得到任何更明智的结果。
小智 6
如果我是对的,您只想立即加载关联的子集。那么,为了做到这一点,您需要智胜轨道。您基本上可以创建另一个关联,例如“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
Run Code Online (Sandbox Code Playgroud)
现在您需要立即加载最高等级关联。
Parent.eager_load(:highest_grades)
Run Code Online (Sandbox Code Playgroud)
这基本上会加载所有家长以及仅 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` = '
Run Code Online (Sandbox Code Playgroud)
如果您想了解这是如何工作的。请使用此链接作为参考
| 归档时间: |
|
| 查看次数: |
801 次 |
| 最近记录: |