Comprender: opción de fuente de has_one / has_many a través de Rails

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 en Subscription , 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.

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.

La respuesta más simple:

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