2014-08-29 4 views
0

В принципе, Пользователь может участвовать в одном или нескольких событиях как (или потенциально одновременно) как поставщик, так и как член факультета.Мне нужна помощь в правильном формировании этой ассоциации ActiveRecord

По умолчанию пользователь не относится ни к поставщику, ни к члену факультета, а скорее достигает либо (или обоих) статуса (ов) в контексте события (например, пользователь был допущен к событию как член его факультета).

Похоже, что я хочу сказать, что у пользователя много событий через (или и то и другое) продавцов или связующих таблиц факультета, но я не уверен, что я собираюсь представить это в моей модели Rails , Вот что я пытался до сих пор:

class User < ActiveRecord::Base 
    has_many :events through => vendors 
    has_many :events through => faculty 
end 

Вот пример запроса, который я думаю, что я должен был бы сделать:

Select * from vendors where user_id = 1; 
Select * from faculty where user_id = 1; 

Может ли кто-то или иное направление относительно того, как правильно сформировать эта ассоциация ActiveRecord?

Update:

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

id | first_name | last_name | birth_date | city | zip_code | email | type |   created_at   |   updated_at 
----+------------+-----------+------------+------+----------+-------+---------+----------------------------+---------------------------- 
    1 | Akira  | Yamaoka |   |  |   |  | Vendor | 2014-08-30 14:58:26.917333 | 2014-08-30 14:58:26.917333 
    2 | Pyramid | Head  |   |  |   |  | Faculty | 2014-08-30 15:02:04.70209 | 2014-08-30 15:02:04.70209 
+0

Просьба предоставить запросы, которые необходимо внести по этим данным. Конечно, указанное неверно, потому что вы указали две ассоциации с тем же именем, но с разными параметрами. –

+0

Оригинальный пост обновлен. –

+0

Я думаю, вы можете придерживаться 'has_many ... через ...' и использовать наследование одиночной таблицы для установления типов ссылок: общий (не для прямого использования), член и поставщик (унаследованный от общего). Я расскажу больше, когда будет готов. Не стесняйтесь смотреть, как работает STI. –

ответ

2

Однонаправленное наследование может быть тем, что вам нужно. В двух словах: он позволяет нескольким классам с одним и тем же видом данных помещаться в одну таблицу. Единственное требование состоит в том, чтобы эта таблица имела столбец type, a string.

В принципе, речь идет о здравом смысле. Предположим, пользователь может пройти к событию: пропуск поставщика и пропуск участника факультета. У него могут быть оба. Давайте создадим модель Pass, имея в виду, что нам понадобятся разные ее виды. Но мы будем использовать его позже. Сейчас давайте просто придерживаться has_many through:

rails g model Pass type:string user:references event:references 

Migrate это и не нужно будет больше изменять нашу базу данных. Мы изменим только Ruby. Мы должны иметь класс Pass, мы должны отметить его роль в ассоциации:

class Pass < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :event 
end 

Все правильно. Тогда мы будем иметь такую ​​User и Event:

class Event < ActiveRecord::Base 
    has_many :passes 
    has_many :users, through: :passes 
end 

class User < ActiveRecord::Base 
    has_many :passes 
    has_many :events, through: :passes 
end 

Вот где магия STI приходит. Давайте создадим еще два класса.

rails g model VendorPass --no-migration --parent=Pass 
rails g model FacultyPass --no-migration --parent=Pass 

Мы создали несколько классов без таблиц базы данных (они нам не нужны). Они пусты, и мы его не изменим: они наследуют Pass, и это все, что нам нужно.Но нам нужно создать дополнительные ассоциации между нашими User, Event и новыми проходами. В конце концов, я нашел эту работу:

class Event < ActiveRecord::Base 
    # We already had this 
    has_many :passes 
    has_many :users, through: :passes 

    # New stuff! 
    has_many :vendor_passes 
    has_many :vendors, through: :vendor_passes, source: :user 

    has_many :faculty_passes 
    has_many :faculty_members, through: :faculty_passes, source: :user 
end 

class User < ActiveRecord::Base 
    # We already had this 
    has_many :passes 
    has_many :events, through: :passes 

    # New stuff! 
    has_many :vendor_passes 
    has_many :vendor_events, through: :vendor_passes, source: :event 

    has_many :faculty_passes 
    has_many :faculty_events, through: :faculty_passes, source: :event 
end 

Rails сохраняет свое собственное понимание VendorPass, который «это Pass, чьи type является VendorPass», то же самое с FacultyPass.

Хорошие части:

  • Легко представить: структура данных, кажется, здравомыслящая и логичное
  • Мы свободны, чтобы добавить больше типов Pass эсов без изменения базы данных

Плохие детали:

  • Ни в коем случае, чтобы добавить дополнительные поля только для определенных подклассов Pass: все они в той же таблице
  • ассоциации выглядят немного повторяющиеся и громоздким
  • Rails только позволяет type быть string, не самый быстрый тип в сравнение
+0

Спасибо, что нашли время, чтобы обеспечить такой глубокий отклик. Кажется, я вижу, что ты здесь делаешь. Я собираюсь задуматься об этом некоторое время. –

+0

Это очень хорошо подходит для счета. Ты качаешь, чувак. Шутки в сторону. –

0

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

class User < ActiveRecord::Base 
    has_many :tickets 
    has_many :events, through: :tickets 
end 

class Event < ActiveRecord::Base 
    has_many :tickets 
    has_many :users, through: :tickets 
end 

class Ticket < ActiveRecord::Base 
    belongs_to :event 
    belongs_to :user 
    belongs_to :vendor 
    belongs_to :faculty 
end 

class Faculty < ActiveRecord::Base 
    has_many :tickets 
end 

class Vendor < ActiveRecord::Base 
    has_many :tickets 
end 
Смежные вопросы