Я пытаюсь понять, что это has_many :through
такое и когда его использовать (и как). Однако я этого не понимаю. Я читаю Beginning Rails 3 и пробовал поискать в Google, но не могу понять.
источник
Я пытаюсь понять, что это has_many :through
такое и когда его использовать (и как). Однако я этого не понимаю. Я читаю Beginning Rails 3 и пробовал поискать в Google, но не могу понять.
Допустим, у вас есть две модели: User
и Group
.
Если вы хотите, чтобы пользователи принадлежали к группам, вы можете сделать что-то вроде этого:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
Что, если вы хотите отслеживать дополнительные метаданные по ассоциации? Например, когда пользователь присоединился к группе, или, возможно, какова роль пользователя в группе?
Здесь вы делаете ассоциацию объектом первого класса:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Это вводит новую таблицу и удаляет group_id
столбец из таблицы пользователя.
Проблема с этим кодом в том, что вам придется обновлять все, где еще вы используете пользовательский класс, и изменять его:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Этот тип кода - отстой, и вносить подобные изменения в него очень сложно.
has_many :through
дает вам лучшее из обоих миров:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
Теперь вы можете относиться к нему как к обычному has_many
, но при необходимости использовать модель ассоциации.
Обратите внимание, что вы также можете сделать это с помощью has_one
.
Изменить: упростить добавление пользователя в группу
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user
модель метод для добавления группы. Что-то вроде той правки, которую я только что сделал. Надеюсь это поможет.user.groups << group
? Или всем занимается эта ассоциация?Допустим, у вас есть эти модели:
Автомобиль
has_one :engine
Двигатель
belongs_to :car
Двигатель
has_many :pistons
Поршень
belongs_to :engine
has_many :pistons, through: :engine
Поршень автомобиля
has_one :car, through: :engine
По сути, вы делегируете модельное отношение другой модели, поэтому вместо вызова
car.engine.pistons
вы можете просто сделатьcar.pistons
источник
Таблицы соединения ActiveRecord
has_many :through
иhas_and_belongs_to_many
отношения функционируют через таблицу соединений , которая является промежуточной таблицей, представляющей отношения между другими таблицами. В отличие от запроса JOIN, данные фактически хранятся в таблице.Практические различия
С
has_and_belongs_to_many
, вам не нужен первичный ключ, и вы получаете доступ к записям через отношения ActiveRecord, а не через модель ActiveRecord. Обычно вы используете HABTM, когда хотите связать две модели с помощью отношения «многие ко многим».Вы используете
has_many :through
отношения, когда хотите взаимодействовать с объединенной таблицей как с моделью Rails, в комплекте с первичными ключами и возможностью добавлять настраиваемые столбцы к объединенным данным. Последнее особенно важно для данных, которые относятся к объединенным строкам, но на самом деле не относятся к связанным моделям - например, для хранения вычисленного значения, полученного из полей в объединенной строке.Смотрите также
В Руководстве по ассоциациям Active Record рекомендация гласит:
источник