141 votes

Quand utiliser une relation "has_many :through" dans Rails ?

J'essaie de comprendre ce que has_many :through est et quand l'utiliser (et comment). Cependant, je ne comprends pas. J'ai lu Beginning Rails 3 et j'ai essayé de chercher sur Google, mais je n'arrive pas à comprendre.

246voto

cpuguy83 Points 1811

Disons que vous avez ces modèles :

Car
Engine
Piston

Une voiture has_one :engine
Un moteur belongs_to :car
Un moteur has_many :pistons
Piston belongs_to :engine

Une voiture has_many :pistons, through: :engine
Piston has_one :car, through: :engine

Essentiellement, vous déléguez une relation de modèle à un autre modèle, donc au lieu de devoir appeler car.engine.pistons vous pouvez simplement faire car.pistons

193voto

Ben Scheirman Points 23590

Disons que vous avez deux modèles : User y Group .

Si vous vouliez que les utilisateurs appartiennent à des groupes, vous pourriez 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, quand 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 fonction group_id de la table de l'utilisateur.

Le problème avec ce code est que vous devriez mettre à jour chaque fois que vous utilisez la classe utilisateur et la modifier :

user.groups.first.name

# becomes

user.group_memberships.first.group.name

Ce type de code est nul, et il rend l'introduction de changements comme celui-ci pénible.

has_many :through vous offre le meilleur des deux mondes :

class User < ActiveRecord::Base
  has_many :group_memberships
  has_many :groups, :through => :group_memberships  # Edit :needs to be plural same as the has_many relationship   
end

Maintenant, vous pouvez le traiter comme une has_many mais bénéficiez du modèle d'association quand vous en avez besoin.

Notez que vous pouvez également le faire avec has_one .

Editer : Faciliter l'ajout d'un utilisateur à un groupe

def add_group(group, role = "member")
  self.group_associations.build(:group => group, :role => role)
end

21voto

CodeGnome Points 25402

Tables de jonction ActiveRecord

has_many :through y has_and_belongs_to_many Les relations fonctionnent par le biais d'un joindre la table qui est une table intermédiaire qui représente la relation entre d'autres tables. Contrairement à une requête JOIN, les données sont réellement 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 par des relations ActiveRecord plutôt que par un modèle ActiveRecord. Vous utilisez généralement HABTM lorsque vous souhaitez relier deux modèles avec une relation many-to-many.

Vous utilisez un has_many :through lorsque vous souhaitez interagir avec la table jointe en tant que modèle Rails, avec des clés primaires et la possibilité d'ajouter des colonnes personnalisées aux données jointes. Cette dernière possibilité est particulièrement importante pour les données qui sont pertinentes pour les lignes jointes, mais qui n'appartiennent pas vraiment aux modèles liés - par exemple, le stockage d'une valeur calculée dérivée des champs de la ligne jointe.

Voir aussi

Sur Guide des associations d'enregistrements actifs La recommandation dit ceci

La règle la plus simple est que vous devez configurer une relation has_many :through si vous devez travailler avec le modèle de relation en tant qu'entité indépendante. Si vous n'avez pas besoin d'utiliser le modèle de relation, il peut être plus simple de configurer une relation has_and_belongs_to_many (mais vous devrez penser à créer la table de jonction dans la base de données).

Vous devez utiliser has_many :through si vous avez besoin de validations, de rappels ou d'attributs supplémentaires sur le modèle de jointure.

2voto

rogal111 Points 2672

Lire la suite de la section Rails Tutorial et has_many : à travers la section du guide des rails .

Cet article devrait vous expliquer quand utiliser has_many :through .

2voto

PriteshJ Points 5097

Je vous suggère de passer par

http://guides.rubyonrails.org/association_basics.html

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Ce sont les documents officiels de rails et ils sont très bien documentés.

également http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many .

Il y a aussi un screencast par ryan bates ici. http://railscasts.com/episodes/47-two-many-to-many

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X