在 Rails 中将 Where 和 or 与两个属性一起使用

Using Where and or with two attributes in Rails

我想使用范围函数并进行查询,以便它应用范围,并应用两个条件之一:

我正在寻找这样的东西:

apply_scopes(Message).where((user_id: current_user.id) || (recipient_id: current_user.id))

但是明显有语法错误

什么时候使用:

apply_scopes(Message).where(user_id: current_user.id).or(Message.where(recipient_id: current_user.id))

我的印象是没有考虑范围。

请问 WHEREOR 两个变量的正确使用方法是什么?

使用Model.or时要小心。 SQL 中的 OR 的优先级低于 AND,因此您可以获得令人惊讶的结果。例如,假设有一个范围 some_scope,它包括 id = 6 但不包括 id = 11 的结果,那么这个:

Model.some_scope.where(id: 6).or(Model.where(id: 11))

会像这样产生 SQL:

select * from models where some_scope and id = 6 or id = 11

并添加括号以突出优先级:

select * from models where (some_scope and id = 6) or id = 11

,我们发现查询同时找到了 611

但是如果我们在末尾应用作用域:

Model.where(id: 6).or(Model.where(id: 11)).some_scope

我们得到 SQL 这样的:

select * from models where (id = 6 or id = 11) and some_scope

并且只找到 6

我可能会使用字符串条件和命名占位符:

apply_scopes(Message).where('messages.user_id = :uid or messages.recipient_id = :uid', uid: current_user.id)

以免混淆。在这种特殊情况下,如果要隐藏字符串,还可以向 Message 添加另一个范围:

scope :involving, ->(user) { where('messages.user_id = :uid or messages.recipient_id = :uid', uid: user) }

大概你会做很多这样的事情,所以额外的范围是有意义的。