代码之家  ›  专栏  ›  技术社区  ›  Mr. Tao

自引用Rails HABTM关联只能单向工作

  •  1
  • Mr. Tao  · 技术社区  · 6 年前

    我有文件,其中一些是相关的 关系是对称的 .也就是说,我试图根据HABTM的指示为两者建立这种关系的模型 association join table

    我能做到 d1.related_documents << d2 对于文档的两个实例。 d1.related_documents 工作并返回相关文件,但 d2.related_documents 返回一个空集。

    我已经声明了如下表和模型:

    • 文档表

      create_table :documents do |t|
        t.string :matter
        t.string :url_id, unique: true
        t.text :body
      
        t.timestamps
      end
      
    • 联接表

      create_join_table :documents, :documents, table_name: :related_documents, id: false do |t|
        t.references :referent, foreign_key: { to_table: :documents, 
                                               primary_key: :url_id }, index: true
        t.references :reference, foreign_key: { to_table: :documents, 
                                                primary_key: :url_id }, index: true
        end
      end
      
    • 模型

      has_and_belongs_to_many :related_documents, join_table: :related_documents, 
                                                  class_name: "Document", 
                                                  foreign_key: :referent_id, 
                                                  association_foreign_key: :reference_id
      
    1 回复  |  直到 6 年前
        1
  •  1
  •   stwienert    6 年前

    自引用habtm在标准Rails工具箱之外有一点。您需要调整finder\u sql或有2个关系:

    has_and_belongs_to_many :related_documents, join_table: :related_documents, 
                                                class_name: "Document", 
                                                foreign_key: :referent_id, 
                                                association_foreign_key: :reference_id
    has_and_belongs_to_many :referenced_documents, join_table: :related_documents, 
                                                class_name: "Document", 
                                                foreign_key: :reference_id, 
                                                association_foreign_key: :referent_id
    

    如果需要将结果合并到一个SQL中,则需要调整Finder SQL,请参见例如。 https://gist.github.com/srpouyet/4121517

    has_and_belongs_to_many :related_documents,
                              class_name: 'Document',
                              join_table: :related_documents,
                              foreign_key: :reference_id,
                              association_foreign_key: :referent_id,
                              uniq: true,
                              finder_sql: proc { 
         %(SELECT DISTINCT "documents".* FROM "documents"
           INNER JOIN "related_documents" 
             ON "documents"."id" = "related_documents"."referent_id"
           WHERE "related_documents"."reference_id" =  #{id}
           UNION
           SELECT DISTINCT "documents".* FROM "documents"
           INNER JOIN "related_documents" 
             ON "documents"."id" = "related_documents"."reference_id"
           WHERE "related_documents"."referent_id" =  #{id} 
           )}