Rails 5:ActiveRecord或查询


Answers:


228

能够链接or连同条款where条款ActiveRecord查询将在现有的Rails 5。请参阅相关讨论和请求请求

因此,您将能够在Rails 5中执行以下操作:

为了得到一个postid1或2:

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)

3
我如何获得(A || B)&&(C || D)。我尝试了Post.where(a).or(Post.where(b))。where(c).or(Post.where(d)),但它生成为:(A || B)&& C || D
伊姆兰·艾哈迈德

3
@Imran我相信Post.where(a).or(Post.where(b)).where(Post.where(c).or(Post.where(d)))这应该创建(a || b)&&(c || d)
Engineersmnky

1
@Imran这似乎不适用于我:我明白了ArgumentError: Unsupported argument type: #<MyModel::ActiveRecord_Relation:0x00007f8edbc075a8> (MyModel::ActiveRecord_Relation)
Suan

5
等价于.or的一个关系并产生一个.merge。(A || B)&&(C || D)可以由Post.where(a).or(Post.where(b))。merge(Post.where(c).or(Post.where(d )))
Siim Liiser

2
@MathieuJ。它是ActiveRecord :: Relation#merge。api.rubyonrails.org/classes/ActiveRecord/...
西姆·Liiser


6

(只是KM Rakibul Islam的答案的补充。)

使用范围,代码可以变得更漂亮(取决于外观):

scope a,      -> { where(a) }
scope b,      -> { where(b) }

scope a_or_b, -> { a.or(b) }

5

我需要做一个 (A && B) || (C && D) || (E && F)

但是在Rails 5.1.4的当前状态下,使用Arel或链完成此操作太复杂了。但是我仍然想使用Rails生成尽可能多的查询。

所以我做了一个小技巧:

在我的模型中,我创建了一个私有方法,称为sql_where

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(...)
nar8789

在使用合并之前查看此内容-github.com/rails/rails/issues/33501
Aarthi

1

Rails 5具有使用的or子句的功能where。例如。

User.where(name: "abc").or(User.where(name: "abcd"))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.