如何在ActiveRecord查询中基于Factory类名动态替换关联表名
动态替换ActiveRecord查询中的关联表名
问题场景
现有如下查询代码:
factory.workers.where.not(confirmed_at:nil).where(job_roles: {heavy_lifting:true, sensitive_area: false}).pluck(:work_capacity)
但关联表名并非固定为job_roles,而是取决于factory的类名:
- 当
factory.class.name == "DistributionCenter"时,对应表名是distribution_center_roles - 当
factory.class.name == "AutomotiveAssemblyPlant"时,对应表名是automotive_assembly_plant_roles - 以此类推,共有5种不同的factory类型
希望能动态匹配关联表名,避免硬编码或多分支判断。
可行的优雅实现
完全不需要用多分支判断,利用Rails自带的字符串转换方法就能动态生成正确的表名:
# 先生成对应表名 role_table = factory.class.name.underscore + "_roles" # 代入查询 factory.workers.where.not(confirmed_at: nil) .where(role_table => { heavy_lifting: true, sensitive_area: false }) .pluck(:work_capacity)
或者直接写成一行:
factory.workers.where.not(confirmed_at: nil) .where(factory.class.name.underscore + "_roles" => { heavy_lifting: true, sensitive_area: false }) .pluck(:work_capacity)
原理说明:
Rails的underscore方法会自动把驼峰格式的类名(比如AutomotiveAssemblyPlant)转换成蛇形小写字符串(automotive_assembly_plant),加上后缀_roles后正好匹配你需要的关联表名,完美适配所有factory类型。
不推荐的多分支写法
虽然你提到的多分支判断也能实现功能,但维护成本很高——新增factory类型时必须手动添加分支,代码冗余且容易出错,因此不建议使用:
if factory.is_a?(DistributionCenter) factory.workers.where.not(confirmed_at:nil).where(distribution_center_roles: {heavy_lifting:true, sensitive_area: false}).pluck(:work_capacity) elsif factory.is_a?(AutomotiveAssemblyPlant) factory.workers.where.not(confirmed_at:nil).where(automotive_assembly_plant_roles: {heavy_lifting:true, sensitive_area: false}).pluck(:work_capacity) # 更多分支... end
内容的提问来源于stack exchange,提问作者daveasdf_2
相关产品推荐
相关产品推荐

