It's pretty easy to do polymorphic associations in Rails: A Picture can belong to either a BlogPost or an Article. But what if you need the relationship the other way around? A Picture, a Text and a Video can belong to an Article, and that article can find all media by calling @article.media
This example shows how to create an ArticleElement join model that handles the polymorphic relationship. To add fields that are common to all polymorphic models, add fields to the join model.
@Ajedi32 Trying to figure out the answer to your question has helped me get a better understanding of Rails polymorphism. Here's my answer, it might help someone else who comes across this.
The way polymorphism in Rails works: there is one – and only one – class (per polymorphic relationship) that belongs_to other unrelated classes. These other classes can have either a
has_one
or ahas_many
relationship to the belonging model. More concretely, there is a) one class,Polymorph
, withbelongs_to :polymorphable, polymorphic: true
, and b) one or more classes thathas_one
orhas_many :polymorphs, as: polymorphable
. Thus, Picture and Video cannot both have the polymorphic belongs_to. Further, the has_many association cannot be polymorphic.Basically, with "belongs_to, polymorphable" Rails uses the
polymorphable_id
andpolymorphable_type
columns in the underlying table as a foreign_key and table selector, respectively. Normally, belongs to just indicates there is a foreign key, and Rails infers the table name based onbelongs_to
's argument. With polymorphism, it is switching the table based on the_type
. That should provide further clarity on why two tables cannot belong_to the same:symbol
.Based on the needs of the data domain, it might be possible that ArticleElement is not necessary; i.e. Article belongs_to: :element, polymorphic: true. In this case though, ArticleElement is currently acting as a join table between multiple Elements (which happens to not actually be a table) and multiple Articles.