避免Rails中的多态关联

时间:2012-03-09 23:24:39

标签: ruby-on-rails polymorphic-associations surrogate-key

(抱歉任何不好的英语)

假设我有模型A,B,C。每个模型都有一个地址。

在“SQL反模式:避免数据库编程的陷阱”一书中(第7章 - 多态关联) 有一个通过使用“公共超级表”(也称为基表或祖先表)来避免这种关联的方法。

多态,它将是:

table addresses:
    id: integer
    parent_type:string  # 'A', 'B' or 'C'
    parent_id: integer

我知道您可以使用交叉表,但以下解决方案看起来更加精致:

该配方建议创建一个只有id字段(代理键或伪键)的超级表(寻址),而不是将A,B,C与地址多态关联。然后,其他表引用寻址。这样,作者说,“你可以依靠外键强制执行数据库的数据完整性”。 所以,它将是:

table addressing
    id: integer
table addresses
    id: integer
    addressing_id: integer  (foreign_key)
    zip: string
table a
    id: integer
    addressing_id: integer  (foreign_key)
    name: string
table b
    id: integer
    addressing_id: integer  (foreign_key)
    name: string
table c
    id: integer
    addressing_id: integer  (foreign_key)
    name: string

SQL查询将如下所示:

SELECT * from a
  JOIN address USING addressing_id
  WHERE a.addressing_id = 1243 

问题是:如何在Rails中编写这样的场景?我试过几次没有成功。

1 个答案:

答案 0 :(得分:1)

对象A,B和C每个都有一个地址吗? 或许多地址?从下面的评论看,每个对象看起来都有一个地址。

如果每个对象只有一个地址,您只需将外键放入带有地址ID的A / B / C对象中即可。让House或Office对象有一个地址:

class House < ActiveRecord::Base
  belongs_to :address
end

class Office < ActiveRecord::Base
  belongs_to :address
end

您的officehouses数据库表need to have a foreign key address_id。 这样,您就可以使用house.addressoffice.address

等内容访问对象的地址

如果这些对象可以有多个地址,则解决方案取决于A / B / C对象。如果它们相关,您可以使用单表继承 - Rails supports this pattern well - 但没有更多信息,很难说哪种方法最好。