【发布时间】:2015-12-21 13:46:05
【问题描述】:
如何在 Rails 5 ActiveRecord 中进行or 查询?另外,是否可以在 ActiveRecord 查询中将or 与where 链接起来?
【问题讨论】:
标签: ruby-on-rails ruby activerecord ruby-on-rails-5 rails-activerecord
如何在 Rails 5 ActiveRecord 中进行or 查询?另外,是否可以在 ActiveRecord 查询中将or 与where 链接起来?
【问题讨论】:
标签: ruby-on-rails ruby activerecord ruby-on-rails-5 rails-activerecord
Rails 5 中将提供在 ActiveRecord 查询中链接 or 子句和 where 子句的功能。请参阅related discussion and the pull request。
因此,您将能够在 Rails 5 中执行以下操作:
要获得带有id 1 或2 的post:
Post.where('id = 1').or(Post.where('id = 2'))
其他一些例子:
(A && B) || C:
Post.where(a).where(b).or(Post.where(c))
(A || B) && C:
Post.where(a).or(Post.where(b)).where(c)
【讨论】:
Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d))) 这应该创建 (a || b) && (c || d)
ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
(只是对 K M Rakibul Islam 答案的补充。)
使用范围,代码可以变得更漂亮(取决于眼睛看):
scope a, -> { where(a) }
scope b, -> { where(b) }
scope a_or_b, -> { a.or(b) }
【讨论】:
我需要做一个 (A && B) || (C && D) || (E && F)
但是在 Rails 5.1.4 的当前状态中,这太复杂了,无法使用 Arel 或链来完成。
但我仍然想使用 Rails 生成尽可能多的查询。
所以我做了一个小技巧:
在我的模型中,我创建了一个名为 sql_where 的 private 方法:
private
def self.sql_where(*args)
sql = self.unscoped.where(*args).to_sql
match = sql.match(/WHERE\s(.*)$/)
"(#{match[1]})"
end
接下来在我的范围内,我创建了一个数组来保存 OR
scope :whatever, -> {
ors = []
ors << sql_where(A, B)
ors << sql_where(C, D)
ors << sql_where(E, F)
# Now just combine the stumps:
where(ors.join(' OR '))
}
这将产生预期的查询结果:
SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)).
现在我可以轻松地将它与其他范围等结合起来,而不会出现任何错误的 OR。
我的 sql_where 采用正常的 where 子句参数的美妙之处在于:
sql_where(name: 'John', role: 'admin') 将生成(name = 'John' AND role = 'admin')。
【讨论】:
.merge 作为 && 的等价物,并构建一个适当的树来捕获您的括号。类似于...(scopeA.merge(scopeB)).or(scopeC.merge(scopeD)).or(scopeE.merge(scopeF)),假设每个作用域都类似于Model.where(...)
Rails 5 可以使用or 子句和where。
例如。
User.where(name: "abc").or(User.where(name: "abcd"))
【讨论】: