2010-10-13 6 views
3

J'ai appliqué des associations de style has and belongs to many à un projet sur lequel je travaillais, mais parce que je voulais capturer des informations supplémentaires dans mon modèle de jointure, je le mets implicitement en place par l'intermédiaire de la plus élaborée. belongs_to/has_many approche au lieu de has_and_belongs_to_many. Après avoir trébuché d'abord sur ce point, j'ai appris que je devais ces deux définitions dans mon modèle utilisateur (et même dans le contre-modèle Afficher):ActiveRecord apparemment redondant has_many definition

has_many :saved_shows 
has_many :shows, :through :saved_shows 

Tout fonctionne, et ma question est plus sur la conception du Rails syntaxe, parce que je veux m'assurer que je ne manque pas la plus grande image ici: pourquoi le premier est-il nécessaire? Si nous établissons qu'un utilisateur peut accéder à une liste de spectacles via un intermédiaire avec un nom non standard de , pourquoi également établir has_many :saved_shows?

Je suppose que je ne suis pas le premier à avoir rencontré un problème sur celui-ci, donc je suis curieux de savoir pourquoi Rails nécessite cette définition apparemment redondante. Est-ce juste une syntaxe mal choisie ou y a-t-il un design plus profond?

Répondre

3

Rails utilise l'option :through pour référencer une autre association que vous avez déjà définie. Je pense que c'est ce qui fait que vous pouvez d'abord créer des associations complexes sans les définir et les référencer dans la même ligne.

Par exemple, considérez ceci (inutilement complexe) par exemple:

has_many :users, :class_name => 'Person', :foreign_key => 'owner_id' 
has_many :tasks, :through => :users, :class_name 'Job' 

Il n'y a aucun moyen propre d'exprimer tout cela en ligne d'information.

En outre (vous n'êtes pas sûr si vous indiquez ceci dans votre question), vous pouvez accéder explicitement aux deux associations directement. Donc, si un utilisateur has_many :tasks, et has_many :milestones, :through => :tasks, vous pouvez et veut accéder à la fois @user.tasks et @user.milestones.

Il n'est donc pas seulement utile de parcourir une table de jointure dans votre exemple (deux clés étrangères, horodatages et éventuellement un attribut ou deux). Vous pouvez utiliser des modèles de grande taille avec has_many :through.

Est-ce que cela aide à répondre à votre question? Vous n'êtes pas sûr de ce que vous savez déjà.

+1

Cela fait beaucoup de sens maintenant. Je n'avais pas encore envisagé de scénarios plus complexes, comme votre exemple l'indique, car ma première application n'en avait pas encore besoin. –