Database relationships for polymorphic

Currently polymorphic-associations use the _id and _type

      t.bigint  :imageable_id
      t.string  :imageable_type

However it would be nice, for database constraint reasons, and data integrity at db level that it could be possible to have:

      t.references  :product
      t.references  :employee

and then have

class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: [:product, :employee]
  belongs_to :employee, optional: true
  belongs_to :product, optional: true

I think the major reason, off the top of my head, that would be an issue is that without further code or database constraints you could have a Picture belong_to both an Employee and a Product, where as as currently designed, it enforces only a single imageable record that it belongs_to.

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.