Reputation: 863
I have documents and some of them are related and the relation is symmetric. That said, I tried to model this relation according to HABTM instructions for both association and join table.
I can do d1.related_documents << d2
for two instances of Document. d1.related_documents
works and returns related documents, but d2.related_documents
returns an empty set.
I have declared tables and model as follows:
documents table
create_table :documents do |t|
t.string :matter
t.string :url_id, unique: true
t.text :body
t.timestamps
end
join table
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
the model
has_and_belongs_to_many :related_documents, join_table: :related_documents,
class_name: "Document",
foreign_key: :referent_id,
association_foreign_key: :reference_id
Upvotes: 1
Views: 353
Reputation: 3632
A self referential habtm is a little outside the standard Rails toolbox. You need to adjust the finder_sql or have 2 relations:
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
If you need to unionize the results into one SQL, you need to adjust the Finder-SQL, see e.g. 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}
)}
Upvotes: 1