# Polymorphic Associations ###### tags: `Polymorphic`, `Association`, `Sequelize`, `SQLAlchemy`, `One-to-Many` `Many-to-Many` >Note: This page is for a high level overview of polymorphic associations. If you've read this already or know that you need to set up some polymorphic associations in your project, there are links (currently only SQLAlchemy) at the bottom. ## Where do I start? ### Step 1: Do I even need this? Something to consider before you jump into this guide is whether or not you even need a polymorphic association. This type of association is extremely handy for allowing a table to be associated with many other tables through the same system. However, it would be absolute overkill if your app doesn't need that kind of flexibility. Are you adding comments on posts? Great! That's a fun feature, and doesn't need a polymorphic association to tie them together. Are we allowing comments on posts and *also* nested comments? Okay, now a polymorphic association can shine. What about images? Can posts have multiple images? Are we allowing users to put 1 image on either a comment or a post? Both are cool, but neither requires a polymorphic association (if a post/comment only gets one image, you could always put the image url on the Post/Comment model). However, if *both* posts and comments can have *multiple* photos, a polymorphic association can clean up your database a bit. ### Step 2: I still don't know if I need it. Let's take a look at a previously mentioned example: an application where you can add multiple images to either a post or a comment. If we didn't want to use a polymorphic association, we could do this in one of two ways: ![](https://i.imgur.com/GQ58MMf.png) In this first example, we're putting two foreign keys on the Images table, but we'll only ever use one. That means we have to allow both of those keys to be null, so that an image can be either associated with a post or a comment. This is not great design, and if we ever decided we wanted to be able to add an image to something else (let's say the user's profile), we'd have to add *another* foreign key to Images for that! ![](https://i.imgur.com/EpxBj4O.png) In this second example, we rid ourselves of the need for those weird null foreign keys, but now we have an extra table! Again, not great design. ![](https://i.imgur.com/7Nfaoij.png) Here we have the polymorphic association. It's a bit strange to look at, because where is the `imageable_type` coming into play? But that will be vital in the code. The `imageable_id` will refer to the primary key of another table, as we're used to by now. The `imageable_type`, however, will be used to say which model we're connecting this Image to, whether it be a Post or a Comment. So the combination of `imageable_id` and `imageable_type` will be used to pinpoint both which table *and* which row in that table we're connecting this to. > Note: if you're looking through resources on the internet for information on polymorphic associations, you may find examples with attributes like `commentable_id` & `commentable_type` or `imageable_id` & `imageable_type`. I used `imageable_id` and `imageable_type` here. It really just means that if a Post can be connected to a Images table through the `imageable_id` & `imageable_type` attributes, then it's "imageable"! > Note 2: I've used an enum for the `imageable_type` in the polymorphic association. You could also use a string. The tradeoff that you get is a little less setup when using a string in exchange for less protection on the values that could be used for `imageable_type`. We'll be using enums in the tutorials I've linked below, but if you decide to use a string datatype instead you can just ignore enum-specific changes to files. ### Step 3: Okay, I'm sold. But can I get an example with **code**? Absolutely! Here are the links to simple walkthrough examples of polymorphic associations with a few different ORMs | Backend Setup | Walkthrough | | ------------------ |:---------------------- | | Flask/SQLAlchemy | [:link:][SQLAlchemy] | | Express/Sequelize | [:link:][Sequelize] | | Rails/Active Record | Future Addition | [Sequelize]: https://hackmd.io/@chrisoney/Hy2-OwNo_ [SQLAlchemy]: https://hackmd.io/@chrisoney/rkNWNTt_d