Grundlegendes: Quelloption von has_one / has_many durch Rails


184

Bitte helfen Sie mir das Verständnis :sourceMöglichkeit has_one/has_many :throughVereins. Die Erklärung der Rails-API macht für mich wenig Sinn.

"Gibt den Namen der Quellzuordnung an, die von verwendet wird has_many :through => :queries. Verwenden Sie ihn nur, wenn der Name nicht aus der Zuordnung abgeleitet werden kann. Es has_many :subscribers, :through => :subscriptionswird entweder nach :subscribersoder :subscribernach Subscriptiongesucht, sofern nicht a :sourceangegeben ist."

Antworten:


237

Manchmal möchten Sie unterschiedliche Namen für unterschiedliche Zuordnungen verwenden. Wenn der Name, den Sie für eine Zuordnung im Modell verwenden möchten, nicht mit der Zuordnung im :throughModell übereinstimmt , können Sie ihn :sourceangeben.

Ich denke nicht, dass der obige Absatz viel klarer ist als der in den Dokumenten, also hier ein Beispiel. Nehmen wir an , wir haben drei Modelle Pet, Dogund 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

In diesem Fall haben wir uns für den Namespace von entschieden Dog::Breed, da wir Dog.find(123).breedsals nette und bequeme Zuordnung darauf zugreifen möchten .

Wenn wir jetzt eine has_many :dog_breeds, :through => :dogsAssoziation erstellen möchten Pet, haben wir plötzlich ein Problem. Rails kann keine :dog_breedsZuordnung finden Dog, daher kann Rails möglicherweise nicht wissen, welche Dog Zuordnung Sie verwenden möchten. Geben Sie ein :source:

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

Mit :sourceweisen wir Rails an , nach einer Zuordnung:breedsDog zu suchen, die für das Modell aufgerufen wird (da dies das verwendete Modell ist :dogs), und diese zu verwenden.


2
Ich denke, Sie wollten, dass Ihr Tier der letzten Klasse Klasse Pet heißt, nur ein Tippfehler, glaube ich.
Kamilski81

3
In dem obigen Beispiel sollte unter der der Verein Dogsein has_many :breedstatt :breedsund dann wird das :sourcesein :breedSingular, die Modellnamen darzustellen, statt :breedswelcher für die Tabellennamen? ZB has_many :dog_breeds, :through => :dogs, :source => :breed(kein sSuffix :breed)?
LazerSharks

1
Ich habe das getestet. es ist einzigartig, kein sSuffix in der:source =>
Anwar

"In diesem Fall haben wir uns für den Namespace" Dog :: Breed "entschieden, da wir auf Dog.find (123) .breeds als nette und bequeme Zuordnung zugreifen möchten." Sie brauchen dafür keinen Namespace, oder?
Jwan622

200

Lassen Sie mich auf dieses Beispiel eingehen:

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

Mit diesem Code können Sie beispielsweise Newsletter.find(id).userseine Liste der Abonnenten des Newsletters abrufen. Wenn Sie jedoch klarer sein und Newsletter.find(id).subscribersstattdessen tippen möchten , müssen Sie die Newsletter-Klasse folgendermaßen ändern:

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

Sie benennen die usersZuordnung in um subscribers. Wenn Sie das nicht :sourceangeben, sucht Rails nach einer Zuordnung, die subscriberin der Subscription-Klasse aufgerufen wird . Sie müssen es anweisen, die userZuordnung in der Abonnementklasse zu verwenden, um die Liste der Abonnenten zu erstellen.


2
Beachten Sie, dass die Singularize-Modellnamen in :source =>und nicht im Plural verwendet werden sollten. Also, :usersist falsch, :userist richtig
Anwar

Dies ist die beste Antwort! Lassen Sie mich nur diesen Teil hervorheben: "Sie benennen die Benutzerzuordnung in Abonnenten um. Wenn Sie die Quelle nicht angeben, sucht Rails in der Abonnementklasse nach einer Zuordnung namens Abonnent."
Brian Joseph Spinos

11

Einfachste Antwort:

Ist der Name der Beziehung in der Tabelle in der Mitte.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.