在 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))
我的印象是没有考虑范围。
请问 WHERE
和 OR
两个变量的正确使用方法是什么?
使用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
,我们发现查询同时找到了 6
和 11
。
但是如果我们在末尾应用作用域:
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) }
大概你会做很多这样的事情,所以额外的范围是有意义的。
我想使用范围函数并进行查询,以便它应用范围,并应用两个条件之一:
我正在寻找这样的东西:
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))
我的印象是没有考虑范围。
请问 WHERE
和 OR
两个变量的正确使用方法是什么?
使用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
,我们发现查询同时找到了 6
和 11
。
但是如果我们在末尾应用作用域:
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) }
大概你会做很多这样的事情,所以额外的范围是有意义的。