在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})
答案 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 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