Rails 6.1.5升级中Squeel查询转写的public_records条件问题
解决Rails 6.1中Squeel查询转ActiveRecord的逻辑问题
核心逻辑回顾
你需要实现的查询规则:
- 若用户所属公司是母公司:返回自身公司 + 同vendor的所有客户公司
- 若非母公司:返回自身公司 + 同vendor且
public_records = true的客户公司
错误原因分析
你的转写失败大概率是因为条件优先级处理错误:
- 直接在单个
where中混用OR和AND会导致SQL解析优先级混乱(比如把(A OR B) AND C变成了A OR (B AND C)的反向逻辑) - 错误地将
public_records条件应用到了所有结果上(包括自身公司),如果自身公司的public_records为false,就会导致无结果返回
正确的ActiveRecord转写方案
方案1:拆分分支清晰写法
# 基础条件:用户自身公司 own_company = Company.where(id: current_user.company.id) if current_user.company.parent? # 母公司逻辑:自身公司 OR 同vendor的所有公司 same_vendor_companies = Company.where(vendor_id: current_user.company.vendor_id) @companies = own_company.or(same_vendor_companies) else # 非母公司逻辑:自身公司 OR(同vendor且public_records为true) same_vendor_public_companies = Company.where( vendor_id: current_user.company.vendor_id, public_records: true ) @companies = own_company.or(same_vendor_public_companies) end
方案2:紧凑链式写法
@companies = Company.where(id: current_user.company.id).or( Company.where(vendor_id: current_user.company.vendor_id).tap do |query| # 非母公司时,给同vendor的查询追加public_records条件 query.where(public_records: true) unless current_user.company.parent? end )
验证与调试步骤
- 检查生成的SQL:执行
@companies.to_sql,对比原Squeel生成的正确SQL,确保非母公司场景下的SQL是:SELECT "companies".* FROM "companies" WHERE ("companies"."id" = ? OR ("companies"."vendor_id" = ? AND "companies"."public_records" = 't')) - 确认
parent?方法的正确性:在Rails 6.1中检查该方法的返回值是否仍为布尔类型,避免因类型变化导致分支判断错误 - 验证自身公司的
public_records值:如果自身公司的public_records为false,错误写法会把它过滤掉,而正确方案会保留这条记录
内容的提问来源于stack exchange,提问作者Scott Milella
相关产品推荐
相关产品推荐

