DEV Community

Cover image for Polymorphic Associations in Rails
Jblengino510
Jblengino510

Posted on

Polymorphic Associations in Rails

When setting up an API in Rails it is crucial to establish how all of your models are going to be connected to each other using Active Record Associations. Polymorphic associations are a little more advanced but can be very useful when your application becomes more complex.

What is Polymorphism?

This is a new concept for me and so far I have learned that polymorphism is a core concept in Object-Oriented-Programming that can be used in many different contexts. This blog will be focusing on this concept in the context of building a Rails API. We can get a more clear understanding of this concept by breaking it down into its Greek roots:
Alt Text
If something is polymorphic it has many forms. For example, numbers in Ruby can be integers(whole #'s), or floats(decimal #'s). A polymorphic association in Rails allows you to associate a single model with multiple models through one association declaration (instead of having multiple belongs_to associations).

Where could this be useful?

Let's say you are building an app that allows users to post content, comment on other posts, and like other posts. Pretty common features that we are all familiar with. Now you want to extend the like feature to comments allowing a user to like individual comments. Your ERD might (or might not) look something like this:
Alt Text
Something like this would work fine, but if you wanted to extend the like feature throughout your app to potential new models in the future you would need to create a separate likes table to the database for each new model you introduce. Overtime this could unnecessarily crowd your database and will end up becoming a repetitive task.

Polymorphic associations

With polymorphic associations we can create a poly_likes table that will act as an interface between other models we want to associate likes to. This isn't the greatest looking ERD but it is looking a little better. Now everytime we want to introduce a new model, we don't need to create a separate likes table to go with that model.

Alt Text

Creating a poly_likes table

To create our new model in the terminal we are going to include an interesting column/value pair.
Alt Text

What does the migration show us?

Alt Text

Lets run the migration and check out the schema

Alt Text

What about the model?

Alt Text
Alt Text
If you're seeing all of this for the first time the syntax might seem a little weird. Why are our associations named with "-able"?

Naming convention for polymorphic associations

If you're familiar with Rails you know that sticking to naming conventions is part of Rails' magic. To make all of this work, Rails uses "-able" with the class name to name polymorphic associations. Basically what we are doing here is making a comment and a post "likeable". Let's make sure the rest of our models are set up to make all of this work:
Alt Text
Alt Text
Alt Text
PLEASE correct me if I am wrong, but I left out the "as: likeable" from the user model because that would make a user likeable which is not what I want in this situation (who knows maybe you want to allow a user to be liked). In this situation I just want a poly_like to be associated with a specific user.

Testing it out in the console

If you take a close look at the query being generated it is looking for a poly_like that has a user_id which is what I wanted. In these examples I did not create any poly_like seeds so we are getting back an empty array, but we can focus on the queries to see how these associations are working.
Alt Text

Now let's check a comment and a post

If we look at the queries again we can see that the likeable_id matches the id of the respective object and the likeable_type references the model type in the form of a string!
Alt Text

Pros

  • Keeps our code DRY by not having to use a bunch of repetitive belongs_to or has_many associations across all of our models.
  • Prevents you from needing to modify existing models and/or adding new join tables to create associations with newly introduced models. (Ex: we did not have to add a separate likes table for the comment & post models like we did in the first ERD.)
  • Makes it easier to add new relationships.

Cons

  • Syntax could take some getting use to at first.
  • No foreign keys.

Conclusion

Polymorphism might be a little tricky to wrap your head around at first, but it is really just a fancy word for saying an object can be related to many different types of objects. In my short experience with polymorphism I can see why this a powerful concept but it is probably not necessary for every situation. I am not an expert on this topic and I used this blog as an opportunity to learn an important concept. Please let me know in the comments below if there are any corrections I need to make to this post or if there are some other practical use cases where polymorphism could really come in handy. Hopefully this post made polymorphism more approachable for you. I linked some very helpful resources below that really helped give me a fundamental understanding.

Resources

https://www.youtube.com/watch?v=pTB0EiLXUC8
https://www.youtube.com/watch?v=SjUVEUCMoX8
https://www.youtube.com/watch?v=5EidzTqsw-E&t=620s
Polymorhpic associations
freeCodeCamp blog on polymorphic associations
Stackoverflow polymorphism

Discussion (0)