J'essaie de comprendre ce que has_many :through
c'est et quand l'utiliser (et comment). Cependant, je ne comprends pas. Je lis Beginning Rails 3 et j'ai essayé Google, mais je n'arrive pas à comprendre.
la source
J'essaie de comprendre ce que has_many :through
c'est et quand l'utiliser (et comment). Cependant, je ne comprends pas. Je lis Beginning Rails 3 et j'ai essayé Google, mais je n'arrive pas à comprendre.
Disons que vous avez deux modèles: User
et Group
.
Si vous souhaitez que les utilisateurs appartiennent à des groupes, vous pouvez faire quelque chose comme ceci:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
Et si vous vouliez suivre des métadonnées supplémentaires autour de l'association? Par exemple, lorsque l'utilisateur a rejoint le groupe, ou peut-être quel est le rôle de l'utilisateur dans le groupe?
C'est ici que vous faites de l'association un objet de première classe:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Cela introduit une nouvelle table et élimine la group_id
colonne de la table de l'utilisateur.
Le problème avec ce code est que vous devez mettre à jour partout où vous utilisez la classe d'utilisateurs et la modifier:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Ce type de code est nul et cela rend l'introduction de changements comme celui-ci douloureux.
has_many :through
vous offre le meilleur des deux mondes:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
Vous pouvez désormais le traiter comme un système normal has_many
, mais profitez du modèle d'association lorsque vous en avez besoin.
Notez que vous pouvez également le faire avec has_one
.
Modifier: faciliter l'ajout d'un utilisateur à un groupe
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user
modèle pour ajouter le groupe. Quelque chose comme la modification que je viens de faire. J'espère que cela t'aides.user.groups << group
? Ou est-ce que tout est géré par cette association?Disons que vous avez ces modèles:
Une voiture
has_one :engine
Un moteur
belongs_to :car
Un moteur
has_many :pistons
Piston
belongs_to :engine
Un
has_many :pistons, through: :engine
piston de voiture
has_one :car, through: :engine
Vous déléguez essentiellement une relation de modèle à un autre modèle, donc au lieu d'avoir à appeler
car.engine.pistons
, vous pouvez simplement fairecar.pistons
la source
Tables de jointure ActiveRecord
has_many :through
et leshas_and_belongs_to_many
relations fonctionnent via une table de jointure , qui est une table intermédiaire qui représente la relation entre d'autres tables. Contrairement à une requête JOIN, les données sont en fait stockées dans une table.Différences pratiques
Avec
has_and_belongs_to_many
, vous n'avez pas besoin d'une clé primaire et vous accédez aux enregistrements via des relations ActiveRecord plutôt que via un modèle ActiveRecord. Vous utilisez généralement HABTM lorsque vous souhaitez lier deux modèles avec une relation plusieurs-à-plusieurs.Vous utilisez une
has_many :through
relation lorsque vous souhaitez interagir avec la table de jointure en tant que modèle Rails, avec des clés primaires et la possibilité d'ajouter des colonnes personnalisées aux données jointes. Ce dernier est particulièrement important pour les données pertinentes pour les lignes jointes, mais n'appartiennent pas vraiment aux modèles associés - par exemple, le stockage d'une valeur calculée dérivée des champs de la ligne jointe.Voir également
Dans A Guide to Active Record Associations , la recommandation se lit comme suit:
la source