принадлежит к набору классов - PullRequest
2 голосов
/ 03 декабря 2011

У меня есть ситуация, с которой я борюсь концептуально. У меня есть класс Media, который представляет (неудивительно) кусочек медиа. Теперь есть много разных классов, которые владеют Media - например, Question может владеть Media объектом, Answer может также владеть Media объектом.

Попытка смоделировать это со стороны класса-владельца очень проста, я просто даю им соответствующие has_one или has_many ассоциации. Однако я борюсь в другом направлении. Носитель не belong_to какой-либо конкретный класс, он может принадлежать к любому из набора классов.

Я подозреваю, что в эти моменты двусмысленности целесообразно просто НЕ аннотировать класс какой-либо ассоциацией belongs_to. Однако я не могу найти никаких документов, подтверждающих это.

Ответы [ 3 ]

2 голосов
/ 03 декабря 2011

То, что вы ищете, это полиморфные отношения.

class Media < ActiveRecord::Base
  belongs_to :mediable, :polymorphic => true
end

class Question < ActiveRecord::Base
  has_many :media, :as => :mediable
end

class Answer < ActiveRecord::Base
  has_many :media, :as => :mediable
end

Я ответил на аналогичный вопрос, когда один и тот же носитель мог принадлежать более чем одной модели. Вы можете найти этот ответ полезным. https://stackoverflow.com/a/8237597/367611

1 голос
/ 03 декабря 2011

Следует заметить, что на самом деле ничто не мешает вам сделать это:

class Media < ActiveRecord::Base
  belongs_to :question
  belongs_to :answer
end

Однако самый большой недостаток этого подхода заключается в том, что в вашей таблице мультимедиа у вас должно быть два столбца внешнего ключа, допускающих обнуляемость -question_id и answer_id.

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

Чтобы решить эту проблемупроблема, у Rails есть полиморфные ассоциации для вас - используя их, медиа могут принадлежать ко многим другим моделям, через одну ассоциацию.

Так что теперь вы можете моделировать свои ассоциации как в ответе @Sean Hill на ваш вопрос:

class Media < ActiveRecord::Base
  belongs_to :mediable, :polymorphic => true
end

class Question < ActiveRecord::Base
  has_many :media, :as => :mediable
end

# etc.

Ваша медиа-таблица будет представлять полиморфную ассоциацию только с одной парой столбцов: mediable_id (некоторое целое число) и mediable_type ('Вопрос' или 'Ответ').

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

t.integer :mediable_id
t.string  :mediable_type

Или, болеепросто с одним столбцом:

t.references :mediable, :polymorphic => true
1 голос
/ 03 декабря 2011

То, что вы делаете - это полиморфная ассоциация учебника. Направляющие имеют на них немножко.

http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

Несколько более сложный поворот ассоциаций - это полиморфная ассоциация. При полиморфных ассоциациях модель может принадлежать нескольким другим моделям в одной ассоциации. Например, у вас может быть модель изображения, которая принадлежит либо модели сотрудника, либо модели продукта.

...