在范围中使用OR与查询

在Rails3中,我有:

Class Teacher # active :boolean has_and_belongs_to_many :subjects Class Subject # active :boolean has_and_belongs_to_many :teachers 

我正在尝试构建一个教师范围,该范围返回所有active或与active Subject相关联的Teachers

这些范围单独工作,但如何将它们作为单个范围与OR组合?

 scope :active_teachers, where(active: true) scope :more_active_teachers, joins(:subjects).where(:subjects => {active: true}) 

我试过这个没有成功:

 scope :active_teachers, where(active: true).or(joins(:subjects) .where(:subjects => {active: true})) 

更新:

我以为我有一个解决方案,但这不再是懒惰的负载,两次打到数据库 – 最重要的是 – 返回一个数组而不是一个AR对象!

 scope :active_teachers, where(active: true) | joins(:subjects).where(:subjects => {active: true}) 

Squeel了你。 更多细节在这里 。

使用它,你可以定义类似的东西:

 class Teacher ... scope :active_teachers, joins{subjects}.where {(active == true) | (subjects.active == true)} ... end 

我认为简短的回答是你做不到的。

代码中的Oring将打破延迟加载…因为您需要数据库来进行评估,所以无法绕过它。 ActiveRecord无法在不单独执行每个子条款的情况下对范围进行评估。

这样的事情应该起作用:

 joins(:subjects).where("subjects.active = true OR teachers.active = true") 

不太优雅,但可以包装成重用方法。

你可以通过下降到AREL来解决这个问题。 有关如何操作,请参阅此SO问题。

AREL OR条件

或者来自AREL源代码README.md 。 我认为(但尚未validation)这将转化为您的特定示例的以下内容。

 teachers.where(teachers[:active].eq(true).or(subjects[:active].eq(true))) 

祝好运!

有一个rails pull请求( https://github.com/rails/rails/pull/9052 ),但与此同时,有人创建了一个猴子补丁,你可以将其包含在初始化程序中,这将允许你做这仍然给你一个ActiveRecord::Relation

https://gist.github.com/j-mcnally/250eaaceef234dd8971b

有了这个,你就可以像这样对你的范围进行OR操作

 Teacher.active_teachers.or.more_active_teachers 

或写一个新的范围

 scope :combined_scopes, active_teachers.or.more_active_teachers