ruby-on-rails-3 - inverse_of - rails references
Comprender: opción de fuente de has_one/has_many a través de Rails (3)
has_one/has_many :through
comprender la opción de :source
de has_one/has_many :through
asociación. La explicación de Rails API tiene muy poco sentido para mí.
"Especifica el nombre de asociación de origen utilizado por
has_many
:through => :queries
.:through => :queries
solo si el nombre no puede inferirse de la asociación.has_many :subscribers, :through => :subscriptions
buscarán:subscribers
o:subscriber
enSubscription
, a menos que se proporcione una:source
".
A veces, quieres usar diferentes nombres para diferentes asociaciones. Si el nombre que desea utilizar para una asociación en el modelo no es el mismo que el de la asociación en el modelo :through
, puede usar :source
para 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
, Dog
y 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
En este caso, hemos elegido el espacio de nombre Dog::Breed
, porque queremos acceder a Dog.find(123).breeds
como una asociación agradable y conveniente.
Ahora, si ahora queremos crear una has_many :dog_breeds, :through => :dogs
en Pet
, repentinamente tenemos un problema. Rails no podrá encontrar una asociación :dog_breeds
en Dog
, por lo que Rails no puede saber qué asociación de Dog
quieres usar. Ingrese :source
:
class Pet < 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 :breeds
en el modelo Dog
(como ese es el modelo utilizado para :dogs
) y la usa.
La respuesta más simple:
Es el nombre de la relación en la tabla en el medio.
Permítanme ampliar ese ejemplo:
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
Con este código, puede hacer algo como Newsletter.find(id).users
para obtener una lista de los suscriptores del boletín. Pero si quiere ser más claro y poder escribir Newsletter.find(id).subscribers
en Newsletter.find(id).subscribers
lugar, debe cambiar la clase Newsletter a este:
class Newsletter
has_many :subscriptions
has_many :subscribers, :through => :subscriptions, :source => :user
end
Está cambiando el nombre de la asociación de users
a subscribers
. Si no proporciona la :source
Rails buscará una asociación llamada subscriber
en la clase de Suscripción. Debes indicarle que use la asociación de user
en la clase de Suscripción para crear la lista de suscriptores.