Ruby data modellng has_many двусторонняя связь

У меня вопрос об определенной модели данных в Ruby. У меня есть набор бизнес-требований:

Пользователь может создавать множество мастерских

Пользователь может посещать множество семинаров

Мастерская имеет одного владельца (пользователя)

В мастерской много участников (пользователей)

Первую часть этого отношения легко настроить:

#user.rb
class User < ActiveRecord::Base
    has_many :workshops
end

#workshop.rb
class Workshop < ActiveRecord::Base
    belongs_to :user
end

Но как мне сделать отношение «другие has_many» от мастерских к пользователям. Могу ли я сделать что-то вроде семинара, принадлежащего :user, :as :owner. и воркшоп has_many :users, :as :members?

Что вы думаете об этом? Что еще хуже, у семинара есть ограничение на количество участников, поэтому мне нужны проверки...

Спасибо, Даниэль


person Daniël Zwijnenburg    schedule 27.06.2012    source источник


Ответы (1)


У вас есть отношение has_many к has_many, поэтому вам нужно создать новую ассоциативную таблицу, чтобы связать отношения (давайте назовем ее посещаемостью):

создать миграцию БД:

рельсы г модель посещаемость

Затем в вашей миграции сделайте что-то вроде:

create_table :attendances do |t|
    t.integer :attendee_id
    t.integer :workshop_id
end

add_index :attendances, :attendee_id
add_index :attendances, :workshop_id
add_index :attendances, [:workshop_id, :attendee_id]

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

Теперь в вашей пользовательской модели:

has_many :attending, through: :attendances, foreign_key: 'attendee_id', class_name: 'Workshop', source: :workshop

В вашей мастерской модели:

has_many :attendees, through: :attendances, class_name: 'User', source: :attendee    

Теперь 'some_user.attending' вернет отношение ActiveRecord всех семинаров, которые посещает some_user, а 'some_workshop.attendees' даст вам всех пользователей, посещающих some_workshop.

person Amir Rubin    schedule 27.06.2012
comment
schweet именно то, что я искал! Спасибо - person Daniël Zwijnenburg; 28.06.2012
comment
Итак, как мне создать запись, чтобы она отображалась как в some_user.attending, так и в some_workshop.attendees? Есть ли более простой способ, чем делать как some_user.attending << some_workshop, так и some_workshop.attendees << some_user? - person Eric; 07.11.2012
comment
@Eric Вот как я обычно это делаю, если у меня уже есть созданные объекты (т.е. без отработки атрибутов) - person Amir Rubin; 09.11.2012
comment
@Eric, вы могли бы просто сделать это @user.attendances.create(workshop: @workshop) и то же самое для @workshop.attendances.create(user: current_user) - person Daniël Zwijnenburg; 22.11.2012