Zrozumienie: opcja źródła has_one / has_many through Rails
184
Proszę o pomoc w zrozumieniu :sourceopcji has_one/has_many :throughstowarzyszenia. Wyjaśnienie interfejsu Rails API nie ma dla mnie większego sensu.
„Określa nazwę powiązania źródłowego używanego przez has_many:through =>
:queries. Użyj go tylko wtedy, gdy nazwy nie można wywnioskować z powiązania.has_many :subscribers, :through => :subscriptions Będzie szukał jednego :subscriberslub :subscriberdrugiego Subscription, chyba że :sourcepodano a.”
Czasami chcesz użyć różnych nazw dla różnych skojarzeń. Jeśli nazwa, której chcesz użyć dla powiązania w modelu, nie jest taka sama jak przypisanie w :throughmodelu, możesz jej użyć :source.
Nie sądzę, aby powyższy akapit był o wiele jaśniejszy niż ten w dokumentacji, więc oto przykład. Załóżmy, że mamy trzy modele Pet, Dogi Dog::Breed.
W tym przypadku wybraliśmy przestrzeń nazw Dog::Breed, ponieważ chcemy uzyskać dostęp Dog.find(123).breedsjako miłe i wygodne skojarzenie.
Teraz, jeśli chcemy teraz utworzyć has_many :dog_breeds, :through => :dogspowiązanie Pet, nagle mamy problem. Railsy nie będą w stanie znaleźć :dog_breedspowiązania Dog, więc Railsy nie mogą wiedzieć, z któregoDog skojarzenia chcesz skorzystać. Wpisz :source:
classPet<ActiveRecord::Base
has_many :dogs
has_many :dog_breeds,:through =>:dogs,:source =>:breeds
end
Z :source, mówimy szyn szukać stowarzyszenie o nazwie :breedsna Dogmodelu (jak to model używany do :dogs), a stosowanie tego.
Myślę, że chciałeś, aby twoja ostatnia klasa Animal nazywała się class Pet, tylko literówka, którą wierzę.
Kamilski81,
3
W powyższym przykładzie, czy stowarzyszenie powinno Dogbyć has_many :breedzamiast, :breedsa następnie :sourcebyć :breedpojedynczym, reprezentujące nazwę modelu, zamiast :breedsktórego reprezentuje nazwę tabeli? Np. has_many :dog_breeds, :through => :dogs, :source => :breed(Bez sprzyrostka :breed)?
LazerSharks
1
Przetestowałem to. jest to liczba pojedyncza, brak sprzyrostka w:source =>
Anwar
„W tym przypadku wybraliśmy przestrzeń nazw Dog :: Breed, ponieważ chcemy uzyskać dostęp do Dog.find (123) .breed jako miłego i wygodnego skojarzenia.” Nie potrzebujesz do tego przestrzeni nazw?
Za pomocą tego kodu możesz zrobić coś takiego, jak Newsletter.find(id).usersuzyskać listę subskrybentów newslettera. Ale jeśli chcesz być bardziej zrozumiały i Newsletter.find(id).subscribersmożesz zamiast tego pisać , musisz zmienić klasę Newsletter na:
classNewsletter
has_many :subscriptions
has_many :subscribers,:through =>:subscriptions,:source =>:user
end
Zmieniasz nazwę userspowiązania na subscribers. Jeśli nie podasz :source, Rails będzie szukał powiązania wywoływanego subscriberw klasie subskrypcji. Musisz powiedzieć mu, aby użył userpowiązania w klasie subskrypcji, aby utworzyć listę subskrybentów.
należy zauważyć, że należy używać nazw modeli w liczbie pojedynczej :source =>, a nie w liczbie mnogiej. Więc :usersjest źle, :userjest poprawne
Anwar
To najlepsza odpowiedź! Pozwólcie, że po prostu podkreślę tę część: „Zmieniasz nazwę powiązania użytkowników z subskrybentami. Jeśli nie podasz: źródła, Rails będzie szukał powiązania zwanego subskrybentem w klasie subskrypcji”.
Dog
byćhas_many :breed
zamiast,:breeds
a następnie:source
być:breed
pojedynczym, reprezentujące nazwę modelu, zamiast:breeds
którego reprezentuje nazwę tabeli? Np.has_many :dog_breeds, :through => :dogs, :source => :breed
(Bezs
przyrostka:breed
)?s
przyrostka w:source =>
Pozwól mi rozwinąć ten przykład:
Za pomocą tego kodu możesz zrobić coś takiego, jak
Newsletter.find(id).users
uzyskać listę subskrybentów newslettera. Ale jeśli chcesz być bardziej zrozumiały iNewsletter.find(id).subscribers
możesz zamiast tego pisać , musisz zmienić klasę Newsletter na:Zmieniasz nazwę
users
powiązania nasubscribers
. Jeśli nie podasz:source
, Rails będzie szukał powiązania wywoływanegosubscriber
w klasie subskrypcji. Musisz powiedzieć mu, aby użyłuser
powiązania w klasie subskrypcji, aby utworzyć listę subskrybentów.źródło
:source =>
, a nie w liczbie mnogiej. Więc:users
jest źle,:user
jest poprawneNajprostsza odpowiedź:
Jest nazwa relacji w tabeli na środku.
źródło