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

36

我想获取所有具有与所提供电子邮件相同或具有相同名字和姓氏的用户。例如:

users = User.where(:first_name => "James", :last_name => "Scott")

这个查询会返回所有名字为 "James" 和 "Scott" 的用户。

users = User.where(:email => "james@gmail.com")

有没有一种方法可以在一个where查询中返回具有相同名字和姓氏以及与电子邮件匹配的用户,或者我需要在两个单独的where查询上进行合并?

将返回电子邮件为“james@gmail.com”的用户。


1
可能是ActiveRecord OR查询的重复问题。 - Andrew Marshall
1
@Trace:你忘记选择答案或者至少给一些反馈了。 - tokland
5个回答

67

Rails 5带有一个or方法

这种方法接受一个ActiveRecord::Relation对象。例如:

User.where(first_name: 'James', last_name: 'Scott')
    .or(User.where(email: 'james@gmail.com'))

3
对于Rails 5应用程序而言,这应该被视为最正确的答案。 - Brent Matzelle
可能更好的写法是 or(unscoped.where(email: 'james@gmail.com')) - akostadinov

16

试试这个:

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

要插入变量:

users = User.where("(first_name = ? and last_name = ?) or email = ?", first_name, last_name, email)

10
如果您喜欢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'))
)

这看起来有点丑陋,但如果你在Arel上使用一些包装器(例如这个),代码会更加简洁:

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

1
有趣的封装,我一直不喜欢使用arel,但是有了这个,我可能会不那么反感它;很好。 - Andrew Marshall

6

如果您不想像其他人一样编写SQL语句,您可以直接访问arel结构(看起来另一个答案有这个)或使用squeel宝石更加优雅地完成:

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

是的,我猜那更像是 Ruby。无论如何,它需要进行一些调整才能使用变量。 - DGM

1

您可以使用字符串条件,例如Client.where("orders_count = ? AND locked = ?", params[:orders], false),并使用ORAND结合使用。但是请注意这些运算符的优先级。

参见Active Record查询接口指南


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接