如何在ActiveRecord查询中使用OR条件

Mat*_*iby 24 activerecord ruby-on-rails ruby-on-rails-3

我想抓住所有提供电子邮件的用户或者名字和姓氏.例如:

users = User.where(:first_name => "James", :last_name => "Scott")
Run Code Online (Sandbox Code Playgroud)

这将返回所有具有名字"James"和"Scott"的用户.

users = User.where(:email => "james@gmail.com")
Run Code Online (Sandbox Code Playgroud)

这将返回用户的电子邮件为"james@gmail.com".

有没有办法做一个where子句来返回具有相同名字和姓氏的用户以及具有在一个where查询中匹配的电子邮件的用户,或者我是否需要在2个单独的where子句中进行合并.

San*_*osh 45

Rails 5附带了一种or方法.

此方法接受一个ActiveRecord::Relation对象.例如:

User.where(first_name: 'James', last_name: 'Scott')
    .or(User.where(email: 'james@gmail.com'))
Run Code Online (Sandbox Code Playgroud)

  • 对于Rails 5应用程序,这应该被认为是最正确的答案. (2认同)

Ani*_*nil 13

试试这个:

users = User.where("(first_name = 'James' and last_name = 'Scott') or email = 'james@gmail.com'")
Run Code Online (Sandbox Code Playgroud)

要插入变量:

users = User.where("(first_name = ? and last_name = ?) or email = ?", first_name, last_name, email)
Run Code Online (Sandbox Code Playgroud)


tok*_*and 9

如果您更喜欢DSL方法(没有SQL),可以使用底层的Arel层:

t = User.arel_table
users = User.where(
  (t[:first_name].eq('Ernie').and(t[:last_name].eq('Scott')).
    or(t[:email].eq('james#gmail.com'))
)
Run Code Online (Sandbox Code Playgroud)

这有点难看,但是如果你在Arel上使用一些包装器(例如,这个),那么代码就更好了:

users = User.where(
  ((User[:first_name] == 'Ernie') & (User[:last_name] == 'Scott')) |
   (User[:email] == 'james#gmail.com')
)
Run Code Online (Sandbox Code Playgroud)


DGM*_*DGM 5

如果您不想像其他人提到的那样编写SQL,您可以直接访问arel结构(看起来就像另一个答案那样)或使用squeel gem更优雅地执行它:

User.where{(first_name == 'Ernie') & (last_name == 'Scott') | (email == 'james#gmail.com')}
Run Code Online (Sandbox Code Playgroud)


kso*_*sol 1

您可以使用字符串条件,如 中Client.where("orders_count = ? AND locked = ?", params[:orders], false),并OR与 结合使用AND。但要小心这些运算符的优先级。

参见Active Record查询接口指南