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:
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:
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.
Creating a poly_likes table
To create our new model in the terminal we are going to include an interesting column/value pair.
What does the migration show us?
Lets run the migration and check out the schema
What about the model?
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:
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.
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!
Pros
- Keeps our code DRY by not having to use a bunch of repetitive
belongs_to
orhas_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
Top comments (0)