我有 2 个模型:Sophead
和SopheadIssue
。
SopheadIssue belongs to Sophead
,
Sophead has many SopheadIssues
(可选(。
我想在 Sophead 模型上为符合 2 个条件之一的 Sophead 模型创建一个范围:
- 索普海德根本没有索普海德问题
- Sophead 没有 SopheadIssue 属性为 (active=true(。
目前,我已经尝试了以下方法:
scope :no_issue, -> { joins(:sophead_issues).where.not("active = ?", true) }
但这不起作用,因为它缺少没有任何Sophead问题的Sopheads。
任何帮助非常感谢。
非常感谢!
问题是joins
INNER JOIN
,它会过滤掉sophead
而没有sophead_issues
。您需要在此处使用left_joins:
scope :no_issue, -> { left_joins(:sophead_issues).where("sophead_issues.active != ? OR sophead_issues.sophead_id IS NULL", true) }
我相信以下内容应该有效,尽管我目前无法测试和确认这一点:
scope :active, -> { joins(:sophead_issues).where.not(sophead_issues: { active: true }) }
scope :no_associations, -> { joins(:sophead_issues).where.not(sophead_issues: { sophead_id: nil }) }
scope :no_issue, -> { active.no_associations }) }
为了我自己的理智,我将其分解为几个查询,尽管如果我能够测试,我想您应该能够使用or
和not
将它们组合在一起。但是,我不确定如何在不对其进行一些测试的情况下实现它。
基本上,active
范围是不言自明的:您可以找到active
设置为true
的sophead_issues
。
no_associations
您的sopheads
没有关联。如果您有兴趣,请在此处了解更多信息。
最后,no_issue
结合了这两种方法,返回您的收藏。
您可以将其重构为一个类方法,或两个链接形成作用域的类方法,具体取决于您的偏好。
编辑:或者使用@IgorDrozdov的方法,这更干净:)(除非你