Пожалуйста, объясните has_many через: источник: Rails Association - PullRequest
3 голосов
/ 25 апреля 2020

Я нашел кучу статей, ответов от stackoverflow и документации к rails об 'source:', но ни одна из них не объясняет эту связь так, как я могу ее понять. Мне нужно максимально упрощенное объяснение этого способа объединения, если это возможно.

Мой пример таков:

Альбом:

    has_many :reviews, :dependent => :destroy
    has_many :reviewers, through: :reviews, source: :user
    belongs_to :user

Рецензия:

    belongs_to :album, optional: true
    belongs_to :user

Пользователь:

    has_many :reviews
    has_many :reviewed_albums, through: :reviews, source: :album
    has_many :albums

В остальной части кода не упоминаются "рецензенты" или "Review_albums", так что это часть, которую я понимаю меньше всего.

Эти имена совершенно не имеет значения?

1 Ответ

4 голосов
/ 25 апреля 2020

TL; DR

source обозначает таблицу, на которую ссылается эта ассоциация, поскольку мы даем ей другое имя, чем просто .users, потому что у нас уже есть belongs_to :user ассоциация.

Длинное объяснение

Я думаю, что проще всего с этой маленькой картинкой, которая в основном представляет собой схему базы данных для моделей, которые вы опубликовали выше.

database schema

У нас есть альбомы, которые принадлежат пользователям, то есть пользователь - это тот, кто создает альбом. У нас также есть обзоры, и они принадлежат ablums, то есть альбом можно рецензировать. И обзор выполняется пользователем, поэтому обзор принадлежит пользователю.

Теперь ассоциации в рельсах - это способ создания методов, которые можно вызывать для записи базы данных, чтобы найти связанную с ней запись.

Мы могли бы получить пользователя из альбома или всех отзывов, сделанных пользователем, например.

album = Album.find(1)
album.user # => returns the creator of the album

user = User.first
user.reviews # => returns all the reviews a user made

Теперь между этими моделями даже больше связей, чем упомянутых выше.

Давайте сначала посмотрим на альбом:

# album.rb
has_many :reviews, :dependent => :destroy
belongs_to :user
has_many :reviewers, through: :reviews, source: :user

Альбом принадлежит одному пользователю, который его создал. Есть много отзывов. И, если мы будем следовать линии от альбомов до обзоров, а затем далее к таблице пользователей, мы увидим, что мы также можем получить доступ к пользователям, которые дали обзоры. Поэтому мы хотели бы сделать что-то вроде

album.reviews.users

Значение: дать мне всех пользователей, которые оставили рецензию на этот альбом. Теперь эта строка кода не будет работать - потому что album.reviews возвращает массив (точнее, объект ActiveRecord :: Relation), и мы не можем просто вызвать .users для этого. Но у нас может быть другая ассоциация

has_many :reviewers, through: :reviews, source: :user

И здесь мы называем ее reviewers, чтобы не путать с методом / ассоциацией .user, который ссылается на создателя. Обычно Rails ссылается на имя таблицы базы данных из имени ассоциации. Поскольку здесь мы даем другое имя, мы должны явно указать имя таблицы БД, на которую мы ссылаемся, и это таблица пользователей.

Итак, в этом суть этой строки - мы создаем еще одну ассоциацию, нам не нужна прямая линия (см. Изображение) между альбомом и пользователем, мы хотим, чтобы пользователи оставили отзыв на этом альбоме, поэтому мы go through проверяем таблицу, а затем мы должны дать имя (source) таблицы, чтобы Rails знал, в какую таблицу смотреть.

И это, наконец, позволит нам написать код вот так:

album = Album.first
album.user # => creator of the album
album.reviewers # => all users that have left a review for this album

Надеюсь, это поможет! Позвольте мне знать, если у вас есть еще вопросы. Может быть, вы можете объяснить другую связь с источником в модели пользователей в комментариях.

...