You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Squeel gem编写的DB查询改写为正确的Active Record语句

重写代码的核心错误

  1. 字段归属错误:parent_vendor_id是vendors表的字段,你错误写在了projects表的查询条件里,导致关联供应商的条件完全没有生效。
  2. 条件逻辑优先级错误:原始逻辑是 A OR B OR (C AND D),你的写法变成了(A OR B OR C) AND D,相当于所有返回结果都必须满足认证已发布,完全不符合原始需求。
  3. ActiveRecord查询语法错误:直接写.or(certifications.donaldson == true)是完全错误的写法,这里的==是Ruby语法,会直接返回布尔值,不会被解析为SQL查询条件,相当于这部分条件完全失效。
  4. 关联类型错误:第二次重写把left_outer_joins(:certifications)改成了内连接joins(:certifications),会直接过滤掉没有关联认证的项目,和原始Squeel使用外连接保留无认证项目的逻辑冲突。

正确实现方案

推荐使用带绑定变量的原生SQL片段实现,逻辑清晰且不易出错:

if donaldson_primary?
  Project.joins(:vendor)
         .left_outer_joins(:certifications)
         .where("projects.vendor_id = :vendor_id OR vendors.parent_vendor_id = :vendor_id OR (certifications.donaldson = TRUE AND certifications.published = TRUE)", vendor_id: vendor_id)
         .distinct
elsif cdti_primary?
  Project.joins(:vendor)
         .left_outer_joins(:certifications)
         .where("projects.vendor_id = :vendor_id OR vendors.parent_vendor_id = :vendor_id OR (certifications.cdti = TRUE AND certifications.published = TRUE)", vendor_id: vendor_id)
         .distinct
end

方案说明

  • 关联逻辑完全对齐原始Squeel:内连接vendor保证项目一定有关联供应商,左外连接certifications保留无认证的项目,只要满足前两个条件即可返回。
  • 用绑定变量传递参数,不存在SQL注入风险,同时完美匹配原始逻辑的条件优先级,不需要处理ActiveRecordor方法要求两边查询结构一致的限制。
  • 代码简洁可读性高,后续维护成本远低于硬凑ActiveRecord DSL的写法。

关于原生SQL方案的疑问解答

只要使用绑定变量传递参数,不要直接拼接用户输入的字符串,where(原生SQL片段)的方案完全没有不良影响,对于多表关联的复杂条件,反而比硬凑ActiveRecord DSL更不容易出错。

内容的提问来源于stack exchange,提问作者Scott Milella

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 11:39:05