Reputation: 4218
I have a situation that I am struggling with conceptually. I have a class Media
, which represents (unsurprisingly) a peice of media. Now, there are many several different classes that own Media
- for example, a Question
can own a Media
object, an Answer
can also own a Media
object.
Trying to model this from the direction of the owning class is easy, I just give them the appropriate has_one
or has_many
associations. However, I am struggling in the other direction. A media does not belong_to
any particular class, it can belong to any of a set of classes.
I suspect that the appropriate thing to do in these moments of ambiguity, is to simply NOT annotate the class with any belongs_to
association. However, I can't find any documentation confirming this.
Upvotes: 2
Views: 217
Reputation: 11198
It should be noticed that nothing really prevents you from doing this:
class Media < ActiveRecord::Base
belongs_to :question
belongs_to :answer
end
However, the biggest disadvantage of this approach is that in your media table you would have to have two nullable foreign key columns - question_id
and answer_id
.
And if you wanted to attach the media to another class, you would have to add another nullable foreign key column to the media table.
To solve this problem, Rails has polymorphic associations for you - using them, the media can belong to many other models, all through a single association.
So now you can model your associations as in @Sean Hill's answer to your question:
class Media < ActiveRecord::Base
belongs_to :mediable, :polymorphic => true
end
class Question < ActiveRecord::Base
has_many :media, :as => :mediable
end
# etc.
Your media table would represent the polymorphic association with just one pair of columns: mediable_id
(some integer) and mediable_type
('Question' or 'Answer').
Don't forget that you will also need to add the columns to the relevant migration (the CreateMedia migration - adjust as needed):
t.integer :mediable_id
t.string :mediable_type
Or, more simply, with just one column:
t.references :mediable, :polymorphic => true
Upvotes: 1
Reputation: 15056
What you're looking for is a polymorphic relationship.
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
I answered a similar question where the same media could belong to more than one model. You may find that answer useful. https://stackoverflow.com/a/8237597/367611
Upvotes: 2
Reputation: 80140
What you're doing is a textbook polymorphic association. The guides has a good bit on them.
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
A slightly more advanced twist on associations is the polymorphic association. With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model.
Upvotes: 1