ActiveRecord条件用于where块内的变量存在

时间:2014-05-08 09:59:13

标签: ruby activerecord ruby-on-rails-4 squeel

我使用Squeel完成了这段代码:

.where {
  [
    entry[:imdb].presence && imdb == entry[:imdb],
    entry[:asin].presence && asin == entry[:asin],
    entry[:upc].presence  && dvd_upc.upc == entry[:upc]
  ].compact.reduce(:|)
}

如果entry[:variable_name]存在,这只会为列创建查询,否则会忽略它,非常方便。生成如下查询:

"SELECT * FROM `table`  WHERE ((`table`.`imdb` = 3026824 OR `table`.`asin` = 'B00E5PHTR8'))"

关于这个块的好处是我不必担心变量是否存在,如果只有一个变量,查询将不使用OR语句等。使用常规条件书写起来要困难得多。

另请注意,当变量不存在时,此查询的重点是不使用 column = NULL。搜索column = NULL将会检索到一堆无用且错误的匹配。

但是,Squeel不再维护,并且在ActiveRecord 4.1(以及Rails 4.1扩展)方面存在各种各样的失败问题。因此,如果我想使用AR 4.1.1及以上,我唯一的选择就是摆脱我所有的吱吱声查询。

我的问题是,这可能与AR .where阻止有关吗?我似乎无法找到答案而不是,这是不可能的。

2 个答案:

答案 0 :(得分:1)

最后,我想出了这个:

unique_query = main_query.where(
      [
          entry[:imdb].presence && "imdb = '#{entry[:imdb]}'",
          entry[:asin].presence && "asin = '#{entry[:asin]}'",
          entry[:upc].presence &&  "relation_table.upc = #{entry[:upc]}"
      ].compact.join(' or ')
  )

这不是很好,因为我在查询中有变量,这对SQL注入是开放的,但我无法想出更好的方法。至少查询源是受控制的(它来自应用程序),因此SQL注入的风险很小。

同样,这不是一个很好的解决方案,但它是我能想到的最好的解决方案。如果有人有更好的解决方案,我很乐意听到它。

答案 1 :(得分:-2)

假设您在db中有Table模型和相应的'table',SQL中的上述查询可以通过 -

在rails中实现
Table.where('(imdb = ?) OR (asin = ?) OR (upc = ?)', entry[:imdb], entry[:asin], entry[:upc])