如何为多态连接表(polymorphic join table)添加Rails关联?
实现多态父子关联的模型配置
第一步:优化迁移文件
你的基础迁移可以添加联合索引来提升多态查询的性能,这在关联查询场景下非常关键:
create_table :sourceables do |t| t.string :object_type, null: false t.bigint :object_id, null: false t.string :source_type, null: false t.bigint :source_id, null: false end # 添加联合索引,加速按类型+ID组合的查询 add_index :sourceables, [:object_type, :object_id] add_index :sourceables, [:source_type, :source_id]
第二步:配置Sourceable模型
这个模型作为连接表的载体,需要定义两个多态关联,分别对应子对象(object)和父对象(source):
# app/models/sourceable.rb class Sourceable < ApplicationRecord # 关联到"子对象"(比如你例子中的Person实例) belongs_to :object, polymorphic: true # 关联到"父对象"(比如你例子中的父母Person实例) belongs_to :source, polymorphic: true end
第三步:配置Person模型
要实现person.sources直接获取该子对象的所有父对象,推荐用has_many :through的方式,这更符合Rails的关联设计规范:
# app/models/person.rb class Person < ApplicationRecord # 先关联到当前Person作为子对象的所有Sourceable记录 has_many :sourceable_child_entries, class_name: "Sourceable", as: :object, dependent: :destroy # 通过中间的sourceable关联,直接获取所有父对象 has_many :sources, through: :sourceable_child_entries, source: :source, source_type: "Person" end
额外扩展(可选)
如果需要反向查询——获取某个Person作为父对象的所有子对象,可以在Person模型中再加一组关联:
# app/models/person.rb class Person < ApplicationRecord # ... 已有的sources关联 ... # 关联到当前Person作为父对象的所有Sourceable记录 has_many :sourceable_parent_entries, class_name: "Sourceable", as: :source, dependent: :destroy # 获取所有子对象 has_many :children, through: :sourceable_parent_entries, source: :object, source_type: "Person" end
关键说明
Rails官方文档的多态示例大多是单方向的(比如评论属于多态的可评论对象),而你这里是双向多态连接表,核心是在连接表模型中定义两个多态belongs_to,再通过主模型的has_many :through关联串联起来,实现你需要的父子查询逻辑。
内容的提问来源于stack exchange,提问作者user2453676
相关产品推荐
相关产品推荐

