Rails范围根据其子级的属性(或没有子级)

时间:2018-08-15 13:49:11

标签: ruby-on-rails ruby activerecord

我有2个模型:SopheadSopheadIssue

SopheadIssue belongs to Sophead

Sophead has many SopheadIssues(可选)。

我想在Sophead模型上为与以下两个条件均匹配的Sopheads创建范围:

  1. Sophead根本没有Sophead的问题
  2. Sophead没有SopheadIssue属性为(active = true)的SopheadIssues。

此刻我已经尝试了以下方法:

scope :no_issue, -> { joins(:sophead_issues).where.not("active = ?", true) }

但是这不起作用,因为它缺少没有任何SopheadIssues的Sophead。

非常感谢任何帮助。
非常感谢!

2 个答案:

答案 0 :(得分:3)

问题在于joinsINNER 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) }

答案 1 :(得分:0)

尽管目前无法测试和确认,但我认为以下方法应该可以工作:

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 }) }

出于我自身的理智,我将其分解为几个查询,尽管我可以进行测试,但我想您应该可以使用ornot将它们组合在一起。但是,我不确定如何在不进行一点测试的情况下实现它。

基本上,active范围是不言自明的:您发现sophead_issues的{​​{1}}设置为active的情况。

true您的no_associations没有关联。如果您有兴趣,请进一步了解here

最后,sopheads将两种方法结合起来,返回您的收藏夹。

您可以根据自己的喜好将其重构为一个类方法,或两个链接形成范围的类方法。

编辑:或者使用@IgorDrozdov的方法,它会更清洁:)(除非您是no_issue。)