OR 运算符在 WHERE 子句中与 Rails 4.2 中的 Arel [英] OR operator in WHERE clause with Arel in Rails 4.2

查看:31
本文介绍了OR 运算符在 WHERE 子句中与 Rails 4.2 中的 Arel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码在 Rails 4.1 中使用 OR 运算符构造了一个有效的 where 子句

The following code constructed a valid where clause with an OR operator in Rails 4.1

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 查询,但它的绑定参数缺少值

In Rails 4.2, the same code generates an SQL query with missing values for it's bind parameters

select * from my_models where attribute1 =  OR attribute2 =  

... 并由于绑定值的缺失值而产生错误.

... and generates an error due to the missing values for the bound values.

Rails 4.2 中使用 OR 运算符生成有效查询的等效代码是什么?

What is the equivalent code in Rails 4.2 to generate a valid query with an OR operator?

该解决方案需要使用 Arel::Nodes::Node 派生对象,以便它本身可以通过 AND 和 OR 分组与其他条件组合.

The solution requires an Arel::Nodes::Node derived object to be used so that it can itself be combined with other conditions via AND and OR groupings.

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 节点.

The conditions var must be a derivative of Arel::Nodes::Node. The above solution works for simple queries, but for more complicated queries, conditions must be an Arel Node to be passed to a final query method.

推荐答案

我正在使用下面的直到 rails 5 出来(在 rails 5 AR 支持 .or):

I'm using the below until rails 5 is out (in rails 5 AR supports .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

有了上面的你可以做到:

With the above you can do:

MyModel.where.or(attribute1: 1, attribute2: 2)
# or
MyModel.where.or(MyModel.where(some conditions), MyModel.where(some other conditions))

这篇关于OR 运算符在 WHERE 子句中与 Rails 4.2 中的 Arel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆