На самом деле вам нужны две разные ассоциации. Первая - это ассоциация "один ко многим". Ленивый способ его настройки:
class Circle < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_many :circles
end
Это связывает пользователей с кругами через столбец внешнего ключа user_id
на кругах. Но это довольно неоднозначно - что означает user.circles? Это круги, созданные пользователем, или те, в которых он состоит? Лучше быть более явным, даже если для этого потребуется некоторая конфигурация:
class RenameUserToCreator < ActiveRecord::Migration[6.0]
def change
rename_column :circles, :user_id, :creator_id
end
end
# rails g model circle
class Circle < ApplicationRecord
belongs_to :creator, class_name: 'User'
end
class User < ApplicationRecord
has_many :created_circles,
class_name: 'Circle',
foreign_key: :creator_id
end
Затем вы хотите добавить участников в круг. Это ассоциация «многие ко многим», которую можно выполнить с помощью has_many through:
или has_or_belongs_to_many
. Оба используют объединяющую таблицу, но has_or_belongs_to_many
не имеет модели и его реальная полезность очень ограничена. При именовании таблиц соединения ленивые соглашения заключаются в том, чтобы просто использовать объединение a & b - CircleUser
, но используйте лучшее имя, если вы можете придумать имя, которое подходит для домена.
class Circle
belongs_to :creator, class_name: 'User'
has_many :memberships
has_many :users, through: :memberships
end
# rails g model membership user:belongs_to circle:belongs_to
class Membership
belongs_to :user
belongs_to :circle
end
class User
has_many :created_circles,
class_name: 'Circle',
foreign_key: :creator_id
has_many :memberships
has_many :circles, through: :memberships
end
Одна вещь, чтобы имейте в виду, что каждая ассоциация ДОЛЖНА иметь уникальное имя. Если бы мы не go выполнили предыдущий шаг и написали:
class User
has_many :circles
has_many :memberships
has_many :circles, through: :memberships
end
Последняя ассоциация просто заткнет предыдущую ассоциацию.