Rails 5:ActiveRecord OR查询

K M*_*lam 106 ruby activerecord ruby-on-rails rails-activerecord ruby-on-rails-5

你如何orRails 5 ActiveRecord中进行查询?此外,是否有可能链orwhere在ActiveRecord的查询?

K M*_*lam 217

Rails 5中提供了在查询中链接or子句和where子句的能力.请参阅相关讨论和拉取请求.ActiveRecord

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

为了得到一个postid1或2:

Post.where('id = 1').or(Post.where('id = 2'))
Run Code Online (Sandbox Code Playgroud)

其他一些例子:

(A && B)|| C:

    Post.where(a).where(b).or(Post.where(c))
Run Code Online (Sandbox Code Playgroud)

(A || B)&& C:

    Post.where(a).or(Post.where(b)).where(c)
Run Code Online (Sandbox Code Playgroud)

  • 等价于.or的一个关系并产生一个and是.merge。(A || B)&&(C || D)可以由Post.where(a).or(Post.where(b))。merge(Post.where(c).or(Post.where(d ))) (4认同)
  • 我怎样才能得到(A || B)&&(C || D).我试过Post.where(a).或(Post.where(b)).其中(c).or(Post.where(d))但是它产生为:(A || B)&& C || d (3认同)
  • @Imran我相信它会是`Post.where(a).或(Post.where(b)).where(Post.where(c).or(Post.where(d)))`这应该创造(a || b)&&(c || d) (3认同)
  • @MathieuJ。它是ActiveRecord :: Relation#merge。https://api.rubyonrails.org/classes/ActiveRecord/SpawnMethods.html#method-i-merge (2认同)

Dip*_*pta 13

我们不需要等待rails 5来使用此OR查询.我们也可以用它rails 4.2.3.有一个补丁包,在这里.

感谢Eric-Guo的gem where-or,现在我们也可以使用这个gem 添加这个OR功能>= rails 4.2.3.


Nic*_*las 6

(只是KM拉基布尔伊斯兰教的答案的补充。)

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

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

scope a_or_b, -> { a.or(b) }
Run Code Online (Sandbox Code Playgroud)


mtr*_*lle 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
Run Code Online (Sandbox Code Playgroud)

接下来,在我的作用域中,我创建了一个数组来保存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 '))
}
Run Code Online (Sandbox Code Playgroud)

将会产生预期的查询结果: 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')