На первый взгляд избыточное определение ActiveRecord has_many - PullRequest
3 голосов
/ 13 октября 2010

Я применяю ассоциации стиля has and belongs to many к проекту, над которым я работаю, но, поскольку я хотел собрать дополнительную информацию в моей модели соединения, я неявно настраиваю ее с помощью более сложной belongs_to / has_many подход вместо has_and_belongs_to_many. Первоначально наткнувшись на это, я узнал, что мне нужны оба этих определения в моей модели User (и то же самое в аналоге Show model):

has_many :saved_shows
has_many :shows, :through :saved_shows

Все работает, и мой вопрос больше касается дизайна синтаксиса Rails, потому что я хочу убедиться, что я не пропускаю более широкую картину: зачем нужен первый? Если мы устанавливаем, что пользователь может получить доступ к списку шоу через промежуточное соединение с нестандартным именем saved_shows, зачем также устанавливать has_many :saved_shows?

Полагаю, я не первый, кто натолкнулся на эту загвоздку, поэтому мне любопытно, почему Rails требует этого, казалось бы, избыточного определения. Это просто неправильно выбранный синтаксис или за ним стоит более глубокий дизайн?

1 Ответ

3 голосов
/ 13 октября 2010

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

Например, рассмотрим этот (излишне сложный) пример:

has_many :users, :class_name => 'Person', :foreign_key => 'owner_id'
has_many :tasks, :through => :users, :class_name 'Job'

Нет простого способа выразить всю эту информацию в строке.

Кроме того (не уверен, подразумеваете ли вы это в своем вопросе), вы можете напрямую получить доступ к обеим ассоциациям. Так что если пользователь has_many :tasks и has_many :milestones, :through => :tasks, вы можете и захотите захотеть получить доступ как к @user.tasks, так и к @user.milestones.

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

Помогает ли это ответить на ваш вопрос? Не уверен, сколько из этого вы уже знаете.

...