在范围中使用OR与查询

时间:2013-05-05 05:14:05

标签: ruby-on-rails ruby-on-rails-3 activerecord

在Rails3中我有:

Class Teacher
  #  active                 :boolean
  has_and_belongs_to_many :subjects

Class Subject
  #  active                 :boolean
  has_and_belongs_to_many :teachers

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

这些范围可以单独使用,但如何将它们作为单个范围与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})

4 个答案:

答案 0 :(得分:5)

你有Squeel救援。更多详情here

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

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

答案 1 :(得分:3)

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

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

以下情况应该起作用:

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

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

答案 2 :(得分:3)

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

AREL OR Condition

或者来自AREL Source Code README.md。我认为(但尚未验证)这将转化为您的特定示例的以下内容。

teachers.where(teachers[:active].eq(true).or(subjects[:active].eq(true)))
祝你好运!

答案 3 :(得分:2)

有一个rails pull请求(https://github.com/rails/rails/pull/9052),但与此同时,有人创建了一个猴子补丁,你可以将其包含在初始化程序中,这样你就可以执行此操作并仍然给你一个{ {1}}:

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

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

ActiveRecord::Relation

或写一个新范围

Teacher.active_teachers.or.more_active_teachers