Rails has_many through - 如何为连接表指定关键列?

时间:2018-05-03 21:59:43

标签: sql ruby-on-rails activerecord

TL;博士

我想将 url_id 用于连接表的两列。 Rails坚持使用文档表中的主键。

我使用 url_id 属性自行引用 Document 类。文档可以引用其他文档。我想将 url_id 的连接表作为连接值,如下所示:

  • 所需状态:

    Documents:           Document relationships:
    
    ID | URL_ID |        REFERRING_ID | REFERENCED_ID |          
    ---|--------|        -------------|---------------|
    1  | 1234   |        1234         | 1266          |
    2  | 1266   |        1234         | 2345          |
    3  | 2345   |        1266         | 426           |
    4  | 426    |        444          | 750           |
    5  | 750    |
    7  | 444    |
    

但我无法说服rails将 url_id 用作 refer_id 键。

使用这样的模式,我可以使用类似下面的SQL片段来获取相关文档。

SELECT "documents".* FROM "documents"
INNER JOIN "document_relationships"
ON "documents"."url_id" = "document_relationships"."referenced_id"
WHERE "document_relationships"."referring_id" = ?

经过ActiveRecord documentation后我能得到的最接近的是:

  • 实际状态:

    REFERRING_ID | REFERENCED_ID |
    -------------|---------------|
    1            | 1266          |
    1            | 2345          |
    2            | 426           |
    7            | 750           |
    

的Nb。 Rails正在使用 document_id 而不是 url_id refer_id 列。

  • 文件类:

    class Document < ApplicationRecord
        has_many :document_relationships, foreign_key: :referring_id
        has_many :related, through: :document_relationships, source: :referenced
    end
    
    class DocumentRelationship < ApplicationRecord
        belongs_to :referring, class_name: "Document"
        belongs_to :referenced, class_name: "Document", primary_key: :url_id
    end
    

1 个答案:

答案 0 :(得分:0)

您必须在 document_relationships - 引用关联的两端设置primary_key:

class Document < ApplicationRecord
  has_many :document_relationships, foreign_key: :referring_id, primary_key: :url_id
  has_many :related, through: :document_relationships, source: :referenced
end

class DocumentRelationship < ApplicationRecord
  belongs_to :referring, class_name: "Document", primary_key: :url_id
  belongs_to :referenced, class_name: "Document", primary_key: :url_id
end

# In case the url_id is not unique do not forget to use sth like Array's #uniq :
# Document.first.related.to_a.uniq(&:url_id)