Comprensión: opción de fuente de has_one / has_many a través de Rails
184
Por favor, ayúdame a entender la :sourceopción de has_one/has_many :throughasociación. La explicación de Rails API tiene muy poco sentido para mí.
"Especifica el nombre de la asociación fuente utilizada por has_many:through =>
:queries. Sólo se debe usar si el nombre no se puede deducir de la asociación. has_many :subscribers, :through => :subscriptionsBuscará cualquiera :subscriberso :subscriberen Subscription, a menos que :sourcese le da."
A veces, desea utilizar diferentes nombres para diferentes asociaciones. Si el nombre que desea usar para una asociación en el modelo no es el mismo que la asociación en el :throughmodelo, puede usarlo :sourcepara especificarlo.
No creo que el párrafo anterior sea mucho más claro que el de los documentos, así que aquí hay un ejemplo. Supongamos que tenemos tres modelos Pet, Dogy Dog::Breed.
En este caso, hemos elegido el espacio de nombres Dog::Breed, porque queremos acceder Dog.find(123).breedscomo una asociación agradable y conveniente.
Ahora, si ahora queremos crear una has_many :dog_breeds, :through => :dogsasociación Pet, de repente tenemos un problema. Rails no podrá encontrar una :dog_breedsasociación Dog, por lo que Rails no puede saber quéDog asociación desea utilizar. Ingrese :source:
classPet<ActiveRecord::Base
has_many :dogs
has_many :dog_breeds,:through =>:dogs,:source =>:breeds
end
Con :source, le estamos diciendo a Rails que busque una asociación llamada :breedsen el Dogmodelo (ya que ese es el modelo utilizado :dogs), y que la use.
Creo que querías decir que tu última clase Animal se llamaría clase Mascota, solo un error tipográfico, creo.
Kamilski81
3
En el ejemplo anterior, ¿debería la asociación bajo Dogser en has_many :breedlugar de :breedsy luego :sourceser :breedsingular, para representar el nombre del modelo, en lugar de :breedscuál representa el nombre de la tabla? Por ejemplo has_many :dog_breeds, :through => :dogs, :source => :breed(sin ssufijo :breed)?
LazerSharks
1
He probado esto. es singular, sin ssufijo en el:source =>
Anwar
"En este caso, hemos elegido el espacio de nombres Dog :: Breed, porque queremos acceder a Dog.find (123) .breeds como una asociación agradable y conveniente". No necesitas un espacio de nombres para eso, ¿verdad?
Con este código, puede hacer algo como Newsletter.find(id).usersobtener una lista de los suscriptores del boletín. Pero si desea ser más claro y poder escribir en su Newsletter.find(id).subscriberslugar, debe cambiar la clase Newsletter a esto:
classNewsletter
has_many :subscriptions
has_many :subscribers,:through =>:subscriptions,:source =>:user
end
Estás cambiando el nombre de la usersasociación a subscribers. Si no proporciona el :source, Rails buscará una asociación llamada subscriberen la clase de Suscripción. Debe indicarle que use la userasociación en la clase Suscripción para hacer la lista de suscriptores.
tenga en cuenta que los nombres de modelo en singular deben usarse en :source =>, no en plural. Entonces, :usersestá mal, :useres correcto
Anwar
¡Esta es la mejor respuesta !, permítanme enfatizar esta parte: "Está cambiando el nombre de la asociación de usuarios a suscriptores. Si no proporciona la fuente: Rails buscará una asociación llamada suscriptor en la clase de Suscripción".
Brian Joseph Spinos
11
Respuesta más simple:
Es el nombre de la relación en la tabla del medio.
Dog
ser enhas_many :breed
lugar de:breeds
y luego:source
ser:breed
singular, para representar el nombre del modelo, en lugar de:breeds
cuál representa el nombre de la tabla? Por ejemplohas_many :dog_breeds, :through => :dogs, :source => :breed
(sins
sufijo:breed
)?s
sufijo en el:source =>
Permítanme ampliar ese ejemplo:
Con este código, puede hacer algo como
Newsletter.find(id).users
obtener una lista de los suscriptores del boletín. Pero si desea ser más claro y poder escribir en suNewsletter.find(id).subscribers
lugar, debe cambiar la clase Newsletter a esto:Estás cambiando el nombre de la
users
asociación asubscribers
. Si no proporciona el:source
, Rails buscará una asociación llamadasubscriber
en la clase de Suscripción. Debe indicarle que use lauser
asociación en la clase Suscripción para hacer la lista de suscriptores.fuente
:source =>
, no en plural. Entonces,:users
está mal,:user
es correctoRespuesta más simple:
Es el nombre de la relación en la tabla del medio.
fuente