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

ericguo · 发布于 2015年9月16日 · 最后由 alvin2ye 回复于 2015年9月21日 · 2050 次阅读
Eda824

社区里面讨论过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'
共收到 17 条回复
96

我要吐了

太复杂的SQL 我一直都是 find_by_sql

De6df3

第二段代码,好乱啊

14358

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

14099
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) 
Eda824

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

14099

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

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

那样写不符合DRY

Eda824

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

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

Eda824

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

7643

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%'))
4755

期待的是

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 的缺点就是在条件一多的时候就容易一大堆括号。

Eda824

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

1

我会用 SQL。

162

涉及到需要用用户界面输入构建动态的复杂查询,我都会推荐用ransack

以上面的查询为例子,构造如下的查询参数就可以实现:

Ref::ToolRecipe.search(
  m: 'and', g: [
    {m: 'or',  g: [{recipe_id_end: 'P12-150MI'}, {recipe_id_end: 'P12457-20NI150MI'}, ... ]},
    {m: 'and', g: {golden_flag_eq: 1, recipe_category_eq: 'PROD'}}
  ]
)
3757

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

6764

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

96

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

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