An Introduction to Polymorphic Associations in Rails
The Polymorphic association is a Ruby on Rails feature that gives us the freedom to structure model relationships based on real life. This means building cleaner more semantic databases. In a polymorphic association, a model (Model A) can belong to either one model or another (Model B, Model C, Model D, etc.) A common use case of polymorphic associations is a “Posts” model. Posts can belong to various other models in the application, for example, A profile, a group, an image, etc. This could be represented well with a Polymorphic Association. The OOP concept of polymorphism, or the ability of an object to take many forms, is the foundational idea of these associations in Rails.
Let’s look at an example —
Let’s say I am the future user of a social-media-application called Accountabilibuddies (a real-but-not-yet-deployed web app that I started building with my friend Nolan Dyke), an app helps small groups and friends stay accountable to each other. As a user on the app, I’ll be able to add a comment to various things like posts, subtasks, images, etc.
This is a great use case for a polymorphic association because every comment will belong to either the Post Model, Subtask Model, or Image Model. (A comment is always written by a user, so we will handle the User Model’s relationship to the Comment Model as a typical one-to-many.) In the visualization below, you can see that depending on what’s being commented on, the Comment instance can point to an instance or Id in one of the three models. This makes sense because a comment can only ever belong to 1 of these models because the comment is only written on one of these models.
The basic structure of a polymorphic association (PA)sets up 2 columns in the comment table. (This is different from a typical one-to-many association, where we’d only need one column that references the id’s of the model it belongs to). For a PA, the first column we need to create is for the selected model. It states what model that this instance is pointing to. The second column we need is a foreign-key column. This points to the instance in the selected model that our comment belongs to. For example, the table below shows user 723 (let’s say his name is Geoff) posting 4 comments. Geoff comments on a post with id 56, two images with ids 12 and 13, and subtask with id 25.
Coding It Out
Writing the code is the easy part! Once you figure out how the relationship works, the syntax to generate the migrations and set up the polymorphic association is super straightforward.
- Generate our User model
rails g model User name:string
2. Generate our Comment Model. Pay attention to the syntax here.
rails g model Comment content:string commented_on_id:integer commented_on_type:string User:references
commented_on_id:integer and commented_on_type:string set up the columns in our Comments table which allow for our polymorphic association.
3. Generate your other Models
rails g model Post
rails g model Subtask
rails g model Image
4. Specify relationships in the Models
And there you go! You’ve set up your first polymorphic association. For more on working with Polymorphic Associations, check out the Ruby Guides 🎉.
Thanks to the lovely people at a recent technical interview for introducing me to the concept with patience. I’m looking forward to writing better model relationships (and refactoring my old project) with this new knowledge. Thanks for reading!