Entendendo: opção de origem has_one / has_many através do Rails
184
Por favor, ajude-me a entender a :sourceopção de has_one/has_many :throughassociação. A explicação da API do Rails faz muito pouco sentido para mim.
"Especifica o nome da associação de origem usado por has_many:through =>
:queries. Apenas use-o se o nome não puder ser deduzido da associação. has_many :subscribers, :through => :subscriptionsProcurará por um :subscribersou :subscriberpor outro Subscription, a menos que :sourceseja fornecido um."
Às vezes, você deseja usar nomes diferentes para diferentes associações. Se o nome que você deseja usar para uma associação no modelo não for o mesmo que a associação no :throughmodelo, você poderá usá :source-lo para especificá-lo.
Não acho que o parágrafo acima seja muito mais claro que o dos documentos, então aqui está um exemplo. Vamos supor que temos três modelos, Pet, Doge Dog::Breed.
Nesse caso, optamos por namespace the Dog::Breed, porque queremos acessar Dog.find(123).breedscomo uma associação agradável e conveniente.
Agora, se agora queremos criar uma has_many :dog_breeds, :through => :dogsassociação Pet, de repente temos um problema. O Rails não conseguirá encontrar uma :dog_breedsassociação Dog; portanto, o Rails não pode saber em qualDog associação você deseja usar. Digite :source:
Eu acho que você quis dizer que a sua última classe Animal seria chamada classe Pet, apenas um erro de digitação, acredito.
27412 Kamilki81
3
No exemplo acima, a associação sob deve Dogser em has_many :breedvez de :breedse depois :sourceser :breedsingular, para representar o nome do modelo, em vez de :breedsqual representa o nome da tabela? Por exemplo has_many :dog_breeds, :through => :dogs, :source => :breed(sem ssufixo :breed)?
LazerSharks
1
Eu testei isso. é singular, sem ssufixo no #:source =>
Anwar
"Neste caso, escolhemos o namespace Dog :: Breed, porque queremos acessar Dog.find (123) .breeds como uma associação agradável e conveniente.". Você não precisa de um espaço para nome, não é?
Com esse código, você pode fazer algo como Newsletter.find(id).usersobter uma lista dos assinantes do boletim. Mas se você quiser ser mais claro e conseguir digitar Newsletter.find(id).subscribers, deve alterar a classe Newsletter para isso:
Você está renomeando a usersassociação para subscribers. Se você não fornecer :source, o Rails procurará uma associação chamada subscriberna classe Subscription. Você precisa dizer para usar a userassociação na classe Subscription para fazer a lista de assinantes.
Dog
ser emhas_many :breed
vez de:breeds
e depois:source
ser:breed
singular, para representar o nome do modelo, em vez de:breeds
qual representa o nome da tabela? Por exemplohas_many :dog_breeds, :through => :dogs, :source => :breed
(sems
sufixo:breed
)?s
sufixo no #:source =>
Deixe-me expandir esse exemplo:
Com esse código, você pode fazer algo como
Newsletter.find(id).users
obter uma lista dos assinantes do boletim. Mas se você quiser ser mais claro e conseguir digitarNewsletter.find(id).subscribers
, deve alterar a classe Newsletter para isso:Você está renomeando a
users
associação parasubscribers
. Se você não fornecer:source
, o Rails procurará uma associação chamadasubscriber
na classe Subscription. Você precisa dizer para usar auser
associação na classe Subscription para fazer a lista de assinantes.fonte
:source =>
, e não no plural. Então,:users
está errado,:user
é corretaResposta mais simples:
É o nome do relacionamento na tabela no meio.
fonte