2011-01-08 9 views
138

Por favor, ayúdame a comprender la opción :source de la asociación has_one/has_many :through. La explicación de Rails API tiene muy poco sentido para mí.Comprensión: opción de fuente de has_one/has_many a través de Rails

"especifica el nombre de la asociación fuente utilizado por has_many:through => :queries. Sólo se debe usar si el nombre no se puede deducir de la asociación . Se viene dada has_many :subscribers, :through => :subscriptions mirada, ya sea para :subscribers o :subscriber en Subscription, a menos que un :source. "

Respuesta

178

A veces, desea utilizar nombres diferentes para diferentes asociaciones. Si el nombre que desea utilizar para una asociación en el modelo no es el mismo que el asociado 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 optado por espacio de nombres del Dog::Breed, porque queremos acceder Dog.find(123).breeds como una asociación agradable y conveniente.

Ahora, si ahora queremos crear una asociación has_many :dog_breeds, :through => :dogs en Pet, de repente tenemos un problema. Rails no podrá encontrar una asociación :dog_breeds en Dog, por lo que Rails no puede saber quéDog asociación que desea utilizar. Introduzca :source: Carriles

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

Con :source, le estamos diciendo a buscar una asociación llama :breeds en el modelo Dog (ya que es el modelo utilizado para :dogs), y usar eso.

+2

Creo que quisiste que tu Animal de última clase se llamara Mascota de clase, solo un error tipográfico, creo. – Kamilski81

+0

¡Gracias, buena captura! – vonconrad

+2

En el ejemplo anterior, la asociación en 'Perro' debe ser' has_many: breed' en lugar de ': breeds' y luego': source' be ': breed' singular, para representar el nombre del modelo, en lugar de': razas' que representa el nombre de la tabla? P.ej. 'has_many: dog_breeds,: through =>: dogs,: source =>: breed' (no' s' sufijo ': breed')? – LazerSharks

152

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 quieres ser más claro y ser capaz de escribir Newsletter.find(id).subscribers lugar, debe cambiar la clase a este boletín:

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

está cambiando el nombre a la asociación userssubscribers. Si no proporciona el :source, Rails buscará una asociación llamada subscriber en la clase de Suscripción. Debe indicarle que use la asociación user en la clase de Suscripción para hacer la lista de suscriptores.

+1

Gracias.Mucho más claro es – Anwar

+2

, tenga en cuenta que los nombres de modelo de singularización se deben usar en ': fuente =>', no en plural. Entonces, ': users' está equivocado,': user' es correcto – Anwar

+0

¡Esta es la mejor respuesta !, permítanme enfatizar esta parte: "Están 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 ". –

5

respuesta más simple:

Es el nombre de la relación en la tabla en el medio.

Cuestiones relacionadas