Ruby on rails 当我可以制作一个简单的has\u many/behing\u时,为什么要使用多态关系?

Ruby on rails 当我可以制作一个简单的has\u many/behing\u时,为什么要使用多态关系?,ruby-on-rails,Ruby On Rails,我正在回顾关联,并偶然发现了这篇关于多态关联的文章。在本文中,它具有以下代码: # Without polymorphism class Post belongs_to :person belongs to :group end class Person has_many :posts end class Group has_many :posts end 本文对上述代码做了如下介绍 通常,为了找出谁拥有某个配置文件,我们查看作为外键的列。外键是用于在相关模型的表中

我正在回顾关联,并偶然发现了这篇关于多态关联的文章。在本文中,它具有以下代码:

# Without polymorphism

class Post
  belongs_to :person
  belongs to :group
end


class Person
   has_many :posts
end


class Group
  has_many :posts
end
本文对上述代码做了如下介绍

通常,为了找出谁拥有某个配置文件,我们查看作为外键的列。外键是用于在相关模型的表中查找相关对象的id

但是,我们的Posts表将有两个相互竞争的外键: 组id和个人id。这会有问题

当我们试图找到一个帖子的所有者时,我们必须指出一点 检查两列以查找正确的外键,而不是 依靠一个。如果我们遇到这样一种情况会发生什么 列有值吗

我看不出这里有什么问题。为什么我不能使用此示例
@post=post.where(组id:1)或post.where(个人id:1)

为什么将关联更改为多态性会使代码更好?例如,
has_many::to
创建一个包含两个外键的表,如rails指南中所示。是的,该示例中的三个模型相互连接,而上面的代码只有两个模型连接在一起。我不明白为什么我会选择多态选项


考虑到多态关联不会生成外键,并且容易受到不正确数据的影响。为什么会更好?谢谢。

多态性允许您重用代码,从而使您的应用程序代码具有可伸缩性。例如,如果我有10个模型都需要一个地址记录,我可以创建一个多态关联,只需要创建两个额外的列。第一列是
可寻址类型
,第二列是
可寻址id
。在任何时候,我都可以抓取一个地址并找到其具有完全相同代码的父级,或者从具有完全相同代码的任何父级创建一个地址。所以我相信你是在说,我不能这样做吗?可以,但如果不使用多态性,则必须为每个父级创建外键。因此,每次要将父模型与子地址关联时,必须使用另一个外键创建另一个迁移,这会阻止您重用代码

因此,在多态关联中,抓取第一个
地址的父级类似于这样

parent = Address.first.addressable
如果没有多态性,它看起来像这样:

def parent_record
    if self.customer_id.present?
        return self.customer
    elsif self.some_other_parent_id.present?
        return self.some_other_parent
    end
end

parent = Address.first.parent_record
此外,还必须为每个关联添加以下代码行。否则您将无法创建记录

 belongs_to :customer, optional: true
 belongs_to :some_other_parent, optional: true
现在,假设您确实希望运行验证,以确保不会意外地将多个关联添加到同一条记录中(如果这样做,将破坏整个过程,并且您的数据将无效,也称为“无价值”)。这将是相当困难的。对于多态性,您不必担心,因为只有一个外键

如果您不实现多态关联,然后尝试使用单表继承,这将使您的代码逻辑很难遵循


这些只是几个小理由,说明为什么应该使用多态关联。此外,这是一种很好的编码实践,当您可以为给定的模型使用不同类型的父模型时,使用它是合乎逻辑的。我希望这有帮助

多态性避免了帖子可能同时来自用户和组的可能性,这在应用程序中不是允许的状态,但数据库允许。两个ID not nil都是您必须在代码中管理的一个条件,如果它恰好为真,您必须对其进行处理。对于给定的场景,以您所表达的方式处理它是可行的,我在过去也这样做过,因为我可以确定一个对象通常仅限于两个相互排斥的关联对象。如果您不能保证这一点,或者已经知道互斥关联对象的数量将大于2,那么我建议使用多态性,因为通过xor关联管理关系详细信息变得非常繁琐和脆弱。感谢您的解释。真的帮了大忙。