根据其子级(或没有子级)的属性进行 rails 范围



我有 2 个模型:SopheadSopheadIssue

SopheadIssue belongs to Sophead

Sophead has many SopheadIssues(可选(。

我想在 Sophead 模型上为符合 2 个条件之一的 Sophead 模型创建一个范围:

  1. 索普海德根本没有索普海德问题
  2. Sophead 没有 SopheadIssue 属性为 (active=true(。

目前,我已经尝试了以下方法:

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

但这不起作用,因为它缺少没有任何Sophead问题的Sopheads。

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

问题是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) }

我相信以下内容应该有效,尽管我目前无法测试和确认这一点:

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范围是不言自明的:您可以找到active设置为truesophead_issues

no_associations您的sopheads没有关联。如果您有兴趣,请在此处了解更多信息。

最后,no_issue结合了这两种方法,返回您的收藏。

您可以将其重构为一个类方法,或两个链接形成作用域的类方法,具体取决于您的偏好。

编辑:或者使用@IgorDrozdov的方法,这更干净:)(除非你

最新更新