Ruby on Rails中joins语句使用OR条件报结构不兼容问题
报错原因
ActiveRecord的or方法对拼接的两个查询关系有强结构一致性要求,两个Relation的joins、includes、group等查询构造参数必须完全匹配才能拼接。你写的scope中,第一个查询分支带了joins(:miq_user_roles)配置,第二个分支没有该关联配置,结构不兼容,因此触发报错。
另外你原本用的joins默认是INNER JOIN(内连接),如果强行给第二个分支加上相同的joins配置,会导致「未关联miq_user_roles、但tenant_id匹配当前租户」的记录被内连接过滤,不符合查询预期。
正确写法
根据业务场景二选一即可:
方案1:左外连接+or方法(推荐,覆盖无关联记录场景)
用left_outer_joins替代内连接,保证tenant_id匹配的记录不会被关联逻辑过滤,此时两个查询分支都带相同的左连接配置,结构兼容:
scope :public_service_templates, -> { left_outer_joins(:miq_user_roles) .where(miq_user_roles: { settings: nil }) .or(where(tenant_id: User.current_tenant)) }
补充:如果你的第一类查询要求「必须存在关联miq_user_roles且settings为nil」,要排除左连接带来的「无关联导致miq_user_roles字段全为nil」的干扰,可以调整条件为:
scope :public_service_templates, -> { left_outer_joins(:miq_user_roles) .where("miq_user_roles.id IS NOT NULL AND miq_user_roles.settings IS NULL OR service_templates.tenant_id = ?", User.current_tenant) }
方案2:内连接+原生SQL条件(适用于关联必然存在的场景)
如果业务上所有tenant_id匹配当前租户的记录,都必然存在对应的miq_user_roles关联,可以直接在where中写原生OR条件,绕开or方法的结构校验:
scope :public_service_templates, -> { joins(:miq_user_roles) .where("miq_user_roles.settings IS NULL OR service_templates.tenant_id = ?", User.current_tenant) }
内容的提问来源于stack exchange,提问作者user630702
相关产品推荐
相关产品推荐

