Ассоциация базы данных, может ли класс has_many и принадлежать_ к одному и тому же объекту?

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

В одном случае класс User является участником, принадлежащим событию, а в другом - хостом, и событие принадлежит им. Я не хочу сохранять это сухим и не создавать отдельные классы пользователей (хост и участник в данном случае), если у меня их тоже нет. Простая объединенная таблица, похоже, не объясняет эту условную ассоциацию. Есть какие-нибудь советы, как это сделать?

класс User ???

класс Событие ????

Спасибо!


person Keith Johnson    schedule 17.04.2013    source источник
comment
Если вы разбираетесь в foreign_keys, вы поймете, почему в этом случае необходима таблица соединений. Когда вы говорите «Пользователь принадлежит_к событию», вы говорите, что идентификатор события находится в атрибуте «event_id» пользователя, как foreign_key ... что означает, что пользователь может принадлежать только одному событию за раз, это нормально, если это ваша цель. Сухой не означает, что не нужно объединять столы ... Объединения - это весело!   -  person omarvelous    schedule 18.04.2013


Ответы (4)


Вам нужно будет создать 2 ассоциации - одну для ссылки на созданные события и одну для ссылки на события, на которые вы подписаны:

create_table :event_subscriptions do |t|
  t.references :subscribed_user
  t.references :subscribed_event
end

create_table :events do |t|
  t.references :user
  # other fields
end

class User < ActiveRecord::Base
  has_many :events               # created Events
  has_many :event_subscriptions, :foreign_key => :subscribed_user_id
  has_many :subscribed_events, :through => :event_subscriptions  # subscribed Events
end

class EventSubscription < ActiveRecord::Base
  belongs_to :subscribed_user, :class_name => 'User'
  belongs_to :subscribed_event, :class_name => 'Event'
end

class Event < ActiveRecord::Base
  belongs_to :user               # the creating User
  has_many :event_subscriptions, :foreign_key => :subscribed_event_id
  has_many :subscribed_users, :through => :event_subscriptions   # subscribed Users
end
person PinnyM    schedule 17.04.2013
comment
Вроде вопрос для новичков, но мне нужно будет вводить внешние ключи в файл db / migrate? - person Keith Johnson; 18.04.2013
comment
Вот что для вас делает t.references. - person PinnyM; 18.04.2013

Я бы порекомендовал вам использовать ассоциацию has_and_belongs_to_many (документация здесь). Основываясь на том, чего вы пытаетесь достичь, я не думаю, что объединенного стола можно избежать. Конечно, это не должно вас расстраивать!

Я бы добавил столбец «роль» типа string в таблицу «Пользователи» (т.е. хост или участник) и использовал бы ассоциацию has_and_belongs_to_many. Обратите внимание: вам нужно будет создать объединенную таблицу users_events, содержащую столбцы :user_id и :event_id.

Затем у вас может быть Пользователь, который играет роль, скажем, «организатор», создает событие и приглашает других пользователей с ролью «участник».

Конечно, это только мое предложение. Есть несколько способов сделать это.

person vich    schedule 17.04.2013

Имейте в виду, что если событие has_many :users, тогда таблица пользователей должна иметь столбец event_id, а пользователь может принадлежать только к одному событию за раз. Я подозреваю, что вам нужны отношения "многие ко многим" между пользователями и событиями. В этом случае вы должны использовать has_and_belongs_to_many :users ассоциацию, задокументированную здесь

Тем не менее, да, у вас может быть несколько отношений в одних и тех же классах.

class Event < ActiveRecord::Base
  has_many :users
  belongs_to :host, :class_name => 'User'
end

В таблице событий будет столбец host_id, но event.host все равно будет возвращать User.

person everett1992    schedule 17.04.2013

Я бы справился с этим с помощью has_many и own_to между пользователем и событием. Пользователь has_many Events и Event принадлежит пользователю.

Остальное будет вашей логикой. Вы хотите, чтобы ваши отношения has_many были вашими владельцами или участниками? Я предполагаю, что has_many относится к владельцам событий.

Оттуда создайте столбец с именем участники в таблице событий. Затем в модели Event или User вы можете создать метод before_save, который вставляет user_id вашего участника.

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

person Charlie May    schedule 17.04.2013