web-dev-qa-db-fra.com

Comprendre: option source de has_one / has_many via Rails

S'il vous plaît aidez-moi à comprendre le :source option de has_one/has_many :through _ association. L’explication de l’API Rails) n’a guère de sens pour moi.

"Spécifie le nom d'association source utilisé par has_many:through => :queries. Utilisez-le uniquement si le nom ne peut pas être déduit de l'association. has_many :subscribers, :through => :subscriptions va rechercher soit :subscribers ou :subscriber sur Subscription, sauf si un :source est donnée. "

174
Tri Vuong

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 identique à l'assocation sur le modèle :through, Vous pouvez utiliser :source Pour le spécifier.

Je ne pense pas que le paragraphe ci-dessus soit beaucoup plus clair que celui de la documentation, alors voici un exemple. Supposons que nous avons trois modèles, Pet, Dog et Dog::Breed.

class Pet < ActiveRecord::Base
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :pet
  has_many :breeds
end

class Dog::Breed < ActiveRecord::Base
  belongs_to :dog
end

Dans ce cas, nous avons choisi l’espace de noms Dog::Breed, Car nous voulons accéder à Dog.find(123).breeds en tant qu’association pratique et agréable.

Maintenant, si nous voulons maintenant créer une association has_many :dog_breeds, :through => :dogs Sur Pet, nous avons soudainement un problème. Rails ne pourra pas trouver d'association :dog_breeds Sur Dog, donc Rails ne peut pas savoir quelle association Dog vous souhaitez utiliser. Entrez :source:

class Pet < ActiveRecord::Base
  has_many :dogs
  has_many :dog_breeds, :through => :dogs, :source => :breeds
end

Avec :source, Nous disons Rails à recherchez une association appelée :breeds Sur le modèle Dog.) (comme c'est le modèle utilisé pour :dogs), et l'utiliser.

221
vonconrad

Permettez-moi de développer cet exemple:

class User
  has_many :subscriptions
  has_many :newsletters, :through => :subscriptions
end

class Newsletter
  has_many :subscriptions
  has_many :users, :through => :subscriptions
end

class Subscription
  belongs_to :newsletter
  belongs_to :user
end

Avec ce code, vous pouvez faire quelque chose comme Newsletter.find(id).users pour obtenir une liste des abonnés à la newsletter. Mais si vous voulez être plus clair et pouvoir taper Newsletter.find(id).subscribers à la place, vous devez changer la classe Newsletter en ceci:

class Newsletter
  has_many :subscriptions
  has_many :subscribers, :through => :subscriptions, :source => :user
end

Vous renommez l'association users en subscribers. Si vous ne fournissez pas le :source, Rails recherchera une association appelée subscriber dans la classe Subscription. Vous devez lui indiquer d'utiliser le user association dans la classe Subscription pour créer la liste des abonnés.

187
Jeremy Ruten

Réponse la plus simple:

Est le nom de la relation dans la table au milieu.

9
andfb18