Понимание: исходная опция has_one / has_many через Rails
184
Пожалуйста, помогите мне понять :sourceвариант has_one/has_many :throughобъединения. Объяснение Rails API для меня мало что значит.
«Определяет имя источника ассоциации используется has_many:through =>
:queries. Только использовать его , если имя не может быть выведено из ассоциации. has_many :subscribers, :through => :subscriptionsБудет искать либо :subscribersили :subscriberна Subscription, если только :sourceне дано.»
Иногда вы хотите использовать разные имена для разных ассоциаций. Если имя, которое вы хотите использовать для ассоциации в модели, не совпадает с именем в :throughмодели, вы можете :sourceуказать его.
Я не думаю, что вышеприведенный абзац намного яснее, чем в документах, так что вот пример. Предположим, у нас есть три модели Pet, Dogи Dog::Breed.
В этом случае мы выбрали пространство имен Dog::Breed, потому что хотим получить доступ к ним Dog.find(123).breedsкак к удобной и удобной ассоциации.
Теперь, если мы теперь хотим создать has_many :dog_breeds, :through => :dogsассоциацию Pet, у нас внезапно возникает проблема. Rails не сможет найти :dog_breedsассоциацию Dog, поэтому Rails не может знать, какуюDog ассоциацию вы хотите использовать. Введите :source:
classPet<ActiveRecord::Base
has_many :dogs
has_many :dog_breeds,:through =>:dogs,:source =>:breeds
end
С помощью :source, мы говорим Rails искать ассоциацию, вызываемую :breedsдля Dogмодели (так как эта модель используется :dogs), и использовать ее.
Я думаю, вы хотели, чтобы ваш последний класс Animal был назван классом Pet, просто опечатка, я верю.
Kamilski81
3
В приведенном выше примере, должна ли ассоциация Dogбыть has_many :breedвместо, :breedsа затем :sourceбыть :breedединственной, чтобы представлять имя модели, а не :breedsпредставлять имя таблицы? Например has_many :dog_breeds, :through => :dogs, :source => :breed(без sсуффикса :breed)?
LazerSharks
1
Я проверял это. это единственное число, без sсуффикса в:source =>
Anwar
«В этом случае мы выбрали пространство имен Dog :: Breed, потому что хотим получить доступ к Dog.find (123) .breeds как к удобной и удобной ассоциации». Вам не нужно пространство имен для этого?
С помощью этого кода вы можете сделать что-то вроде Newsletter.find(id).usersполучения списка подписчиков на рассылку. Но если вы хотите быть более понятным и иметь возможность печатать Newsletter.find(id).subscribersвместо этого, вы должны изменить класс Newsletter на этот:
classNewsletter
has_many :subscriptions
has_many :subscribers,:through =>:subscriptions,:source =>:user
end
Вы переименовываете usersассоциацию в subscribers. Если вы не предоставите :source, Rails будет искать ассоциацию, вызываемую subscriberв классе Subscription. Вы должны указать ему использовать userассоциацию в классе подписки, чтобы составить список подписчиков.
обратите внимание, что имена моделей в единственном числе должны использоваться :source =>, а не во множественном числе. Итак, :usersэто неправильно, :userэто правильно
Анвар
Это лучший ответ! Позвольте мне подчеркнуть эту часть: «Вы переименовываете ассоциацию пользователей в подписчики. Если вы не предоставите: source, Rails будет искать ассоциацию, называемую подписчиком, в классе Subscription».
Dog
бытьhas_many :breed
вместо,:breeds
а затем:source
быть:breed
единственной, чтобы представлять имя модели, а не:breeds
представлять имя таблицы? Напримерhas_many :dog_breeds, :through => :dogs, :source => :breed
(безs
суффикса:breed
)?s
суффикса в:source =>
Позвольте мне расширить этот пример:
С помощью этого кода вы можете сделать что-то вроде
Newsletter.find(id).users
получения списка подписчиков на рассылку. Но если вы хотите быть более понятным и иметь возможность печататьNewsletter.find(id).subscribers
вместо этого, вы должны изменить класс Newsletter на этот:Вы переименовываете
users
ассоциацию вsubscribers
. Если вы не предоставите:source
, Rails будет искать ассоциацию, вызываемуюsubscriber
в классе Subscription. Вы должны указать ему использоватьuser
ассоциацию в классе подписки, чтобы составить список подписчиков.источник
:source =>
, а не во множественном числе. Итак,:users
это неправильно,:user
это правильноСамый простой ответ:
Имя отношения в таблице в середине.
источник