Gem Rails 5 的 where.or 在 Rails 4.2 上也可以使用了。

ericguo · 2015年09月16日 · 最后由 alvin2ye 回复于 2015年09月21日 · 4376 次阅读

社区里面讨论过 or 的写法,现在终于 Rails 5 出了官方的解法,考虑到很大一部分同学要用上 Rails 5 起码还有半年,今天我在bf4 的一个帖子的基础上,做了一个 gems : where-or

总之,终于可以这样写 or 了。

post = Post.where('id = 1').or(Post.where('id = 2'))

或者是一个产品级(也就是写的很差的意思,欢迎大家帮我重写^_^)的用法?

@rms_tool_recipe = Ref::ToolRecipe.all
@lot_recipes.collect(&:recipe).reject { |v| v.length < 3 }
  .collect { |r| r.start_with?('Q') ? 'P' + r[1..-1] : r }.each do |r|
  @rms_tool_recipe = @rms_tool_recipe.or(Ref::ToolRecipe.where('recipe_id LIKE :r', r: "%#{r}"))
end
@rms_tool_recipe = @rms_tool_recipe.where(golden_flag: 1, recipe_category: 'PROD').select('recipe_id')
Rails.logger.info "@rms_tool_recipe: #{@rms_tool_recipe.to_sql}"
@rms_tool_recipe: SELECT "EES_RMS_TOOL_RECIPE"."RECIPE_ID" FROM "EES_RMS_TOOL_RECIPE" WHERE ((((((((((((((((recipe_id LIKE '%P12-150MI') OR (recipe_id LIKE '%P12457-20NI150MI')) OR (recipe_id LIKE '%P12457-20NI150MI')) OR (recipe_id LIKE '%P12457-785X11982-20NI110')) OR (recipe_id LIKE '%1Ynm-785X11982-457um')) OR (recipe_id LIKE '%PULGA-03852')) OR (recipe_id LIKE '%P039441NI00-457(L)')) OR (recipe_id LIKE '%PATN 9 High pressure oven')) OR (recipe_id LIKE '%1 / 3')) OR (recipe_id LIKE '%P03944-1')) OR (recipe_id LIKE '%P03944-00217')) OR (recipe_id LIKE '%P-01322-01258-14X18-0.4X0.4')) OR (recipe_id LIKE '%SDSS Pre-con Pb-Free')) OR (recipe_id LIKE '%SDSS Pre-con Pb-Free')) OR (recipe_id LIKE '%P-ULGA-14X18-03131')) OR (recipe_id LIKE '%TBD')) AND "EES_RMS_TOOL_RECIPE"."GOLDEN_FLAG" = '1' AND "EES_RMS_TOOL_RECIPE"."RECIPE_CATEGORY" = 'PROD'

我要吐了

太复杂的 SQL 我一直都是 find_by_sql

第二段代码,好乱啊

难道最好的写法不是 (Post.where('id = 1') || (Post.where('id = 2'))) 这样?

post = Post.where('id = 1').or(Post.where('id = 2'))

改成这样还不错

post = Post.where('id = 1').or(2)
post = Post.where('id  = ? AND user_id = ?', 1, 1).or(2,2) 

#3 楼 @est #4 楼 @roclv AR 类似 jQuery,要求链式调用,这些都不是链式调用

#5 楼 @ericguo 让 or 可以接受 block 作为参数就可以了。

post = Post.where('id  = ? AND user_id = ?', 1, 1).or(2,2)

那样写不符合 DRY

#2 楼 @huacnlee 需求比较变态,已知一堆程序的字符数组,需要从 EES_RMS_TOOL_RECIPE 表中,找到匹配文件名,使用recipe_id LIKE '%P12457-20NI150MI'匹配,但是显然一条条用 like 查数量会比较多,所以希望一条语句直接捞出来,所以不同的 like 间是 OR 关系,最后还有一个 and 关系。

#1 楼 @alvin2ye 由于 like 数量不限,拼字符串我觉得肯定没有 where.or 好,更不要说拼字符串的 SQL 注入问题了。

#6 楼 @roclv 你这样写目前 rails 5/where-or 里面都是不工作的。

Squeel 做这样的事更专业吧。

names = ['Ernie%', 'Joe%', 'Mary%']
Person.where{name.like_any names}
# => SELECT "people".* FROM "people"
#    WHERE (("people"."name" LIKE 'Ernie%' OR "people"."name" LIKE 'Joe%' OR "people"."name" LIKE 'Mary%'))

期待的是

Post.where(id: 1).or(parent_id: 3)

像你这段

Post.where('id = 1').or(Post.where('id = 2'))

我觉得我还不如直接选择用 arel

posts = Post.arel_table
Post.where(posts[:id].eq(1).or(posts[:id].eq(2))

不过用 arel 的缺点就是在条件一多的时候就容易一大堆括号。

#10 楼 @martin91 承认,所以我举了一个生产的例子,我就料到爱美的 rubyist 肯定要喷这个简单例子不漂亮。 😄

我会用 SQL。

用 arel_helpers,写起来就没那么复杂了.

#14 楼 @riskgod arel_helper 用起来 bug 多么

#7 楼 @ericguo find_by_sql 有防注入的.

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册