To describe a key goal of polymorphism, the polymorphic model should not know all the places it is being utilized. Let’s take your example of imageable
and see what it would look like if it were applied to many additional models. Perhaps Driver
, VehicleCondition
, CustomerLogo
, RMADescription
, and Avatar
, Now your Picture
model ends up with these eight belongs_to
lines:
belongs_to :imageable, polymorphic: [:product, :employee, :driver, :vehicle_condition, :customer_logo, :rma_description, and :avatar]
belongs_to :employee, optional: true
belongs_to :product, optional: true
belongs_to :driver, optional: true
belongs_to :vehicle_condition, optional: true
belongs_to :customer_logo, optional: true
belongs_to :rma_description, optional: true
belongs_to :avatar, optional: true
Probably many database people would be happier about the better relational integrity that this would offer, and of course Rails will let you set things up in this non-polymorphic way where all you lose is the ability to ask any Picture
about its imageable
and get back a variety of different types of object. This isn’t the goal of Rails’ polymorphism, to end up with a bunch of specific foreign keys.
Instead Rails polymorphic associations allow you to not know all the places in which your Picture
model will end up being used. After all, it’s just a picture, and you shouldn’t have to know – no need to make any special accommodations for any piece of code using that picture. Use it where you will. (And for any model that does uses it, the inverse association is established with just: has_many :pictures, as: :imageable
, and it just works.)
Definitely polymorphic associations are a unique beast, and some people love them, and some hate them, to the point that some teams prohibit the use of them. But for those that like them then it can make good sense.