以下代码在Rails 4.1中使用where
运算符构造了一个有效的OR
子句
MyModel.where(
MyModel.where(attribute1: 1, attribute2: 2).where_values.reduce(:or)
)
大致相当于SQL
select * from my_models where (attribute1 = 1 OR attribute2 = 2)
在Rails 4.2中,相同的代码会生成一个SQL查询,该SQL查询的绑定(bind)参数缺少值
select * from my_models where attribute1 = OR attribute2 =
...并由于绑定(bind)值的缺少值而产生错误。
Rails 4.2 中使用OR运算符生成有效查询的等效代码是什么?
编辑:
该解决方案要求使用
Arel::Nodes::Node
派生的对象,以便它本身可以通过AND和OR分组与其他条件组合。rel = MyModel.where(attribute1: 1, attribute2: 2)
conditions = [rel.where_values.reduce(:or).to_sql, *rel.bind_values.map(&:last)]
MyModel.where(conditions)
conditions
var必须是Arel::Nodes::Node
的派生词。以上解决方案适用于简单查询,但对于更复杂的查询,conditions
必须是要传递给最终查询方法的Arel节点。 最佳答案
我正在使用以下内容,直到 rails 5退出(在 rails 5中,AR支持.or
):
ActiveRecord::QueryMethods::WhereChain.class_eval do
def or(*scopes)
scopes_where_values = []
scopes_bind_values = []
scopes.each do |scope|
case scope
when ActiveRecord::Relation
scopes_where_values += scope.where_values
scopes_bind_values += scope.bind_values
when Hash
temp_scope = @scope.model.where(scope)
scopes_where_values += temp_scope.where_values
scopes_bind_values += temp_scope.bind_values
end
end
scopes_where_values = scopes_where_values.inject(:or)
@scope.where_values += [scopes_where_values]
@scope.bind_values += scopes_bind_values
@scope
end
end
通过以上操作,您可以执行以下操作:
MyModel.where.or(attribute1: 1, attribute2: 2)
# or
MyModel.where.or(MyModel.where(some conditions), MyModel.where(some other conditions))
关于ruby-on-rails - WHERE子句中的OR运算符与Rails 4.2中的Arel,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27627390/