代码之家  ›  专栏  ›  技术社区  ›  nathanvda

Rails多态关联(传统数据库)

  •  5
  • nathanvda  · 技术社区  · 15 年前

    我使用的是旧数据库,因此我对数据模型没有任何控制权。他们使用了很多多态的链接/连接表,比如这样

    create table person(per_ident, name, ...)
    
    create table person_links(per_ident, obj_name, obj_r_ident)
    
    create table report(rep_ident, name, ...)
    

    在哪里? obj_name 是表名,并且 obj_r_ident 是标识符。 因此,将按如下方式插入链接报告:

    insert into person(1, ...)
    insert into report(1, ...)
    insert into report(2, ...)
    
    insert into person_links(1, 'REPORT', 1)
    insert into person_links(1, 'REPORT', 2)
    

    然后第1个人将有2个链接的报告,1和2。

    我可以理解拥有这样的数据模型可能带来的好处,但我主要看到一个大缺点:使用约束不可能确保数据完整性。但是,唉,我不能再改变这个了。

    但是为了在Rails中使用它,我研究了多态关联,但是没有找到一种很好的方法来解决这个问题(因为我无法更改列的名称,并且没有找到一种方法来解决这个问题)。

    不过,我确实想出了一个解决办法。请提供建议。

    class Person < ActiveRecord::Base
    
      set_primary_key "per_ident"
      set_table_name "person"
      has_and_belongs_to_many :reports,
                             :join_table => "person_links",
                             :foreign_key => "per_ident",
                             :association_foreign_key => "obj_r_ident",
                             :conditions => "OBJ_NAME='REPORT'"
    end
    
    class Report < ActiveRecord::Base
    
      set_primary_key "rep_ident"
      set_table_name "report"
      has_and_belongs_to_many :persons,
                         :join_table => "person_links",
                         :foreign_key => "obj_r_ident",
                         :association_foreign_key => "per_ident",
                         :conditions => "OBJ_NAME='REPORT'"
    end
    

    这是可行的,但我想知道是否有一个更好的解决方案,使用多态关联。

    2 回复  |  直到 8 年前
        1
  •  1
  •   wesgarrison    15 年前

    当然,您可以重写列名,但是对Rails API的快速扫描没有显示任何地方可以重写多态的“type”列。所以,你不能将其设置为“obj_name”。

    它很难看,但我认为你需要一个HABTM来处理你桌上的每种物体。

    可以 可以这样做:

    {:report => 'REPORT'}.each do |sym, text|
      has_and_belongs_to_many sym,
        :join_table => "person_links",
        :foreign_key => "obj_r_ident",
        :association_foreign_key => "per_ident",
        :conditions => "OBJ_NAME='#{text}'"
    end
    

    至少所有普通的东西都是这样的 DRY 你可以很容易地添加更多的关系。

        2
  •  8
  •   Wei-Liang Chew    8 年前

    至少从轨道4.2.1开始,您可以通过 foreign_type 指定要用于多态关联的“类型”的列的名称。

    http://apidock.com/rails/v4.2.1/ActiveRecord/Associations/ClassMethods/belongs_to