Compréhension: option source de has_one / has_many via Rails
184
Veuillez m'aider à comprendre l' :sourceoption d' has_one/has_many :throughassociation. L'explication de l'API Rails n'a que peu de sens pour moi.
« Indique le nom de l' association source utilisée par has_many:through =>
:queries. Utilisez uniquement si le nom ne peut être déduit de l'association. has_many :subscribers, :through => :subscriptionsCherchera soit :subscribersou :subscribersur Subscription, à moins qu'une :sourceest donnée. »
Parfois, vous souhaitez utiliser des noms différents pour différentes associations. Si le nom que vous souhaitez utiliser pour une association sur le modèle n'est pas le même que l'assocation sur le :throughmodèle, vous pouvez l'utiliser :sourcepour le spécifier.
Je ne pense pas que le paragraphe ci-dessus soit beaucoup plus clair que celui de la documentation, voici donc un exemple. Supposons que nous ayons trois modèles Pet, Doget Dog::Breed.
Dans ce cas, nous avons choisi d'espacer le nom Dog::Breed, car nous voulons y accéder Dog.find(123).breedscomme une association agréable et pratique.
Maintenant, si nous voulons maintenant créer une has_many :dog_breeds, :through => :dogsassociation sur Pet, nous avons soudainement un problème. Rails ne pourra pas trouver d' :dog_breedsassociation sur Dog, donc Rails ne peut pas savoir quelleDog association vous souhaitez utiliser. Entrez :source:
Avec :source, nous demandons à Rails de rechercher une association appelée :breedssur le Dogmodèle (car c'est le modèle utilisé pour :dogs), et de l'utiliser.
Je pense que vous vouliez que votre dernier animal de classe s'appelle Pet de classe, juste une faute de frappe je crois.
Kamilski81 le
3
Dans l'exemple ci - dessus, si la l'association en Dogêtre au has_many :breedlieu de :breedspuis l' :sourceêtre :breedsingulier, pour représenter le nom du modèle, au lieu de ce :breedsqui représente le nom de la table? Par exemple has_many :dog_breeds, :through => :dogs, :source => :breed(pas de ssuffixe :breed)?
LazerSharks
1
J'ai testé ça. il est singulier, pas de ssuffixe dans le:source =>
Anwar
«Dans ce cas, nous avons choisi de nommer Dog :: Breed, car nous voulons accéder à Dog.find (123) .breeds comme une association agréable et pratique.». Vous n'avez pas besoin d'un espace de noms pour cela, n'est-ce pas?
Avec ce code, vous pouvez faire quelque chose comme Newsletter.find(id).usersobtenir une liste des abonnés à la newsletter. Mais si vous voulez être plus clair et pouvoir taper à la Newsletter.find(id).subscribersplace, vous devez changer la classe Newsletter en ceci:
Vous renommez l' usersassociation en subscribers. Si vous ne fournissez pas le :source, Rails recherchera une association appelée subscriberdans la classe Subscription. Vous devez lui dire d'utiliser l' userassociation dans la classe Subscription pour faire la liste des abonnés.
notez que les noms de modèle singularize doivent être utilisés au :source =>pluriel et non au pluriel. Donc, :usersest faux, :userest correct
Anwar
C'est la meilleure réponse!, Permettez-moi de souligner cette partie: "Vous renommez l'association d'utilisateurs en abonnés. Si vous ne fournissez pas le: source, Rails recherchera une association appelée abonné dans la classe d'abonnement."
Brian Joseph Spinos
11
Réponse la plus simple:
Est le nom de la relation dans la table au milieu.
Dog
être auhas_many :breed
lieu de:breeds
puis l':source
être:breed
singulier, pour représenter le nom du modèle, au lieu de ce:breeds
qui représente le nom de la table? Par exemplehas_many :dog_breeds, :through => :dogs, :source => :breed
(pas des
suffixe:breed
)?s
suffixe dans le:source =>
Permettez-moi de développer cet exemple:
Avec ce code, vous pouvez faire quelque chose comme
Newsletter.find(id).users
obtenir une liste des abonnés à la newsletter. Mais si vous voulez être plus clair et pouvoir taper à laNewsletter.find(id).subscribers
place, vous devez changer la classe Newsletter en ceci:Vous renommez l'
users
association ensubscribers
. Si vous ne fournissez pas le:source
, Rails recherchera une association appeléesubscriber
dans la classe Subscription. Vous devez lui dire d'utiliser l'user
association dans la classe Subscription pour faire la liste des abonnés.la source
:source =>
pluriel et non au pluriel. Donc,:users
est faux,:user
est correctRéponse la plus simple:
Est le nom de la relation dans la table au milieu.
la source