Je veux répondre à cette question du point de vue de l'association auto-référencée, pas seulement du has_many: through perspective.
Disons que nous avons un CRM avec des contacts. Les contacts auront des relations avec d'autres contacts, mais au lieu de créer une relation entre deux modèles différents, nous créerons une relation entre deux instances du même modèle. Un contact peut avoir de nombreux amis et se lier d'amitié avec de nombreux autres contacts, nous allons donc devoir créer une relation plusieurs-à-plusieurs.
Si nous utilisons un SGBDR et ActiveRecord, nous utiliserions has_many: through. Ainsi, nous aurions besoin de créer un modèle de jointure, comme l'amitié. Ce modèle aurait deux champs, un contact_id qui représente le contact actuel qui ajoute un ami et un friend_id qui représente l'utilisateur qui se lie d'amitié.
Mais nous utilisons MongoDB et Mongoid. Comme indiqué ci-dessus, Mongoid n'a pas has_many: through ou une fonctionnalité équivalente. Cela ne serait pas si utile avec MongoDB car il ne prend pas en charge les requêtes de jointure. Par conséquent, afin de modéliser une relation plusieurs-plusieurs dans une base de données non SGBDR comme MongoDB, vous utilisez un champ contenant un tableau de clés «étrangères» de chaque côté.
class Contact
include Mongoid::Document
has_and_belongs_to_many :practices
end
class Practice
include Mongoid::Document
has_and_belongs_to_many :contacts
end
Comme l'indique la documentation:
Les relations plusieurs à plusieurs dans lesquelles les documents inverses sont stockés dans une collection distincte du document de base sont définies à l'aide de la macro has_and_belongs_to_many de Mongoid. Cela présente un comportement similaire à Active Record à l'exception qu'aucune collection de jointure n'est nécessaire, les ID de clé étrangère sont stockés sous forme de tableaux de chaque côté de la relation.
Lors de la définition d'une relation de cette nature, chaque document est stocké dans sa collection respective, et chaque document contient une référence «clé étrangère» à l'autre sous la forme d'un tableau.
# the contact document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"practice_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
# the practice document
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"contact_ids" : [ ObjectId("4d3ed089fb60ab534684b7f2") ]
}
Maintenant, pour une association d'auto-référencement dans MongoDB, vous avez quelques options.
has_many :related_contacts, :class_name => 'Contact', :inverse_of => :parent_contact
belongs_to :parent_contact, :class_name => 'Contact', :inverse_of => :related_contacts
Quelle est la différence entre des contacts liés et des contacts ayant plusieurs et appartenant à de nombreuses pratiques? Énorme différence! L'une est une relation entre deux entités. L'autre est une auto-référence.