Rails模型改为多态关联后如何保留Payment调用consultation的能力
结论
可以通过belongs_to实现,你之前的写法不生效是缺少了外键/多态类型的约束配置,根据你的数据表结构可以选下面两种方案:
方案1:表中还保留原有consultation_id字段
只需要补全foreign_key声明即可,避免Rails默认找错关联字段:
class Payment < ActiveRecord::Base belongs_to :paymentable, optional: true, polymorphic: true belongs_to :consultation, class_name: "Consultation", foreign_key: "consultation_id", optional: true end
注意:这种方案会存在数据不一致风险,如果你修改了paymentable关联的Consultation对象,需要手动同步更新consultation_id的值,反之亦然。
方案2:已删除consultation_id,仅用多态字段paymentable_type、paymentable_id
给belongs_to加多态类型过滤条件,指定多态字段作为外键:
class Payment < ActiveRecord::Base belongs_to :paymentable, optional: true, polymorphic: true belongs_to :consultation, -> { where(payments: { paymentable_type: 'Consultation' }) }, class_name: "Consultation", foreign_key: "paymentable_id", optional: true end
这种方案关联的就是多态本身的字段,不会有数据不一致的问题,只有当paymentable_type为Consultation时,consultation关联才会返回对应对象,其他情况返回nil
更简单的替代方案(不需要用belongs_to)
如果不需要用到关联的预加载、链式查询等特性,直接定义实例方法更简洁,后续维护成本更低:
class Payment < ActiveRecord::Base belongs_to :paymentable, optional: true, polymorphic: true def consultation paymentable if paymentable.is_a?(Consultation) end # 可选:加setter方法支持赋值,自动同步多态关联 def consultation=(consultation) self.paymentable = consultation end end
内容的提问来源于stack exchange,提问作者Jeremy Thomas
相关产品推荐
相关产品推荐

