Ruby-on-rails 如何使用 OR 而不是 AND 链接范围查询?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3684311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 23:11:48  来源:igfitidea点击:

How to chain scope queries with OR instead of AND?

ruby-on-railsruby-on-rails-3activerecordrails-activerecord

提问by user410715

I'm using Rails3, ActiveRecord

我正在使用 Rails3,ActiveRecord

Just wondering how can I chain the scopes with OR statements rather than AND.

只是想知道如何使用 OR 语句而不是 AND 来链接作用域。

e.g.

例如

Person.where(:name => "John").where(:lastname => "Smith")

That normally returns:

通常会返回:

name = 'John' AND lastname = 'Smith'

but I'd like:

但我想:

`name = 'John' OR lastname = 'Smith'

回答by Petros

You would do

你会做

Person.where('name=? OR lastname=?', 'John', 'Smith')

Right now, there isn't any other OR support by the new AR3 syntax (that is without using some 3rd party gem).

现在,新的 AR3 语法没有任何其他 OR 支持(即不使用某些 3rd 方 gem)。

回答by Ryan Leaf

According to this pull request, Rails 5 now supports the following syntax for chaining queries:

根据这个 pull request,Rails 5 现在支持以下用于链接查询的语法:

Post.where(id: 1).or(Post.where(id: 2))

There's also a backport of the functionality into Rails 4.2 via this gem.

还有通过这个 gem将该功能反向移植到 Rails 4.2 中

回答by Dan McNevin

Use ARel

使用ARel

t = Person.arel_table

results = Person.where(
  t[:name].eq("John").
  or(t[:lastname].eq("Smith"))
)

回答by daino3

Just posting the Array syntax for samecolumn OR queries to help peeps out.

只需发布同一列 OR 查询的 Array 语法以帮助窥视。

Person.where(name: ["John", "Steve"])

回答by kissrobber

Update for Rails4

Rails4 更新

requires no 3rd party gems

不需要第 3 方宝石

a = Person.where(name: "John") # or any scope 
b = Person.where(lastname: "Smith") # or any scope 
Person.where([a, b].map{|s| s.arel.constraints.reduce(:and) }.reduce(:or))\
  .tap {|sc| sc.bind_values = [a, b].map(&:bind_values) }

Old answer

旧答案

requires no 3rd party gems

不需要第 3 方宝石

Person.where(
    Person.where(:name => "John").where(:lastname => "Smith")
      .where_values.reduce(:or)
)

回答by Simon Perepelitsa

You can also use MetaWheregem to not mix up your code with SQL stuff:

您还可以使用MetaWheregem 来避免将您的代码与 SQL 内容混淆:

Person.where((:name => "John") | (:lastname => "Smith"))

回答by codenamev

In case anyone is looking for an updated answer to this one, it looks like there is an existing pull request to get this into Rails: https://github.com/rails/rails/pull/9052.

如果有人正在寻找此问题的更新答案,似乎有一个现有的拉取请求可以将其放入 Rails:https: //github.com/rails/rails/pull/9052

Thanks to @j-mcnally's monkey patch for ActiveRecord (https://gist.github.com/j-mcnally/250eaaceef234dd8971b) you can do the following:

感谢@j-mcnally 的 ActiveRecord 猴子补丁(https://gist.github.com/j-mcnally/250eaaceef234dd8971b),您可以执行以下操作:

Person.where(name: 'John').or.where(last_name: 'Smith').all

Even more valuable is the ability to chain scopes with OR:

更有价值的是将范围链接到以下内容的能力OR

scope :first_or_last_name, ->(name) { where(name: name.split(' ').first).or.where(last_name: name.split(' ').last) }
scope :parent_last_name, ->(name) { includes(:parents).where(last_name: name) }

Then you can find all Persons with first or last name or whose parent with last name

然后你可以找到所有有名字或姓氏的人或其父母姓氏

Person.first_or_last_name('John Smith').or.parent_last_name('Smith')

Not the best example for the use of this, but just trying to fit it with the question.

不是使用它的最佳示例,而只是试图将其与问题相适应。

回答by Zsolt

For me (Rails 4.2.5) it only works like this:

对我来说(Rails 4.2.5)它只能这样工作:

{ where("name = ? or name = ?", a, b) }

回答by Christian Fazzini

An updated version of Rails/ActiveRecord may support this syntax natively. It would look similar to:

Rails/ActiveRecord 的更新版本可能本身就支持这种语法。它看起来类似于:

Foo.where(foo: 'bar').or.where(bar: 'bar')

As noted in this pull request https://github.com/rails/rails/pull/9052

如本拉取请求中所述https://github.com/rails/rails/pull/9052

For now, simply sticking with the following works great:

就目前而言,只需坚持以下工作即可:

Foo.where('foo= ? OR bar= ?', 'bar', 'bar')

回答by dhulihan

This would be a good candidate for MetaWhere if you're using Rails 3.0+, but it doesn't work on Rails 3.1. You might want to try out squeelinstead. It's made by the same author. Here's how'd you'd perform an OR based chain:

如果您使用的是 Rails 3.0+,这将是 MetaWhere 的一个很好的候选者,但它不适用于 Rails 3.1。您可能想尝试使用squeel。它是由同一作者制作的。以下是您如何执行基于 OR 的链:

Person.where{(name == "John") | (lastname == "Smith")}

You can mix and match AND/OR, among many other awesome things.

您可以混合和匹配 AND/OR 以及许多其他很棒的东西