所以我检查了这个有趣的话题,并会告诉我所知道的。
当你像往常一样在has_many :through中创建对象时:
class Contact
has_many :contactables
has_many :managers, :through => :contactables
end
class Manager
has_many :contactables
has_many :contacts, :through => :contactables
end
class Client
has_many :contactables
has_many :contacts, :through => :contactables
end
class Contactable
belongs_to :contact
belongs_to :manager
belongs_to :client
end
您可以对每个引用的对象使用外键。多态看起来是一个很好的解决方案。所以:
class Contactable
belongs_to :contact
belongs_to :polymorphic_model, polymorphic: true
end
class Contact
has_many :contactables
has_many :managers, :through => :contactables, :source => :polymorphic_model, :source_type => 'Manager'
end
class Manager
has_many :contactables, :as => :polymorphic_model
has_many :contacts, :through => :contactables
end
设置 :as 选项表明这是一个多态
联想
:source => :polymorphic_model 用于告诉 Rails 从子类中获取相关对象。 :source 的含义与:class_name 相同。如果没有这个选项,Rails 会尝试从 Contactables 表中获取关联的 Manager,而它应该通过虚拟 Polymorphic_model 访问。
通过将belongs_to :polymorphic_model 添加到Contactable,您可以使Contact(女巫已经坐在那里,因为belongs_to :contact)与经理或客户相关联,因为这就是多态关联所做的 - 引用两个或多个父表。并且因为 Contact have_many Contactables,同一个 Contact 对象可以与许多经理或客户相关联。所以在你理解之后,看起来真的很简单——Joined 模型属于Contact 并且Joined 模型还通过多态关联持有对Manager 和Client 的引用。因此,为了让 Contact 拥有多个经理,您需要创建另一个属于同一个 Contact,但属于不同 Manager 的 Contactable 对象。看起来效率不高,但就我个人而言,不知道更好的方法..
这是一个经过测试的证明:
Manager.create!(name: "Bravo")
=> #<Manager id: 1, created_at: "2017-04-12 12:17:41", updated_at: "2017-04-12 12:17:41", name: "Bravo">
Manager.create!(name: "Johnny")
=> #<Manager id: 2, created_at: "2017-04-12 12:18:24", updated_at: "2017-04-12 12:18:24", name: "Johnny">
Contact.create!(number:"123")
=> #<Contact id: 1, created_at: "2017-04-12 12:18:59", updated_at: "2017-04-12 12:18:59", number: 123>
c = Contactable.new
c.contact = Contact.first
c.unit = Manager.first
c
=> #<Contactable id: nil, unit_type: "Manager", created_at: nil, updated_at: nil, unit_id: 1, contact_id: 1>
现在要将另一个经理设置为同一个联系人,我们创建一个新的联系人:
cc = Contactable.new
cc.contact = Contact.first
cc.unit = Manager.last
cc
=> #<Contactable id: nil, unit_type: "Manager", created_at: nil, updated_at: nil, unit_id: 4, contact_id: 1>
并获得所有关联:
Contact.first.managers
联系人的数据库:
contact_id
unit_id
unit_type
@Bill Karwin 的一句有趣的话:
多态关联设计打破了关系规则
数据库设计。我不建议使用它。
但这是他很久以前写的。现在可能无关紧要。
Why can you not have a foreign key in a polymorphic association?