Column values for polymorphic associations

Hello all,

I’m working with a legacy schema that uses polymorphism and having some trouble getting AR to cooperate with it’s original design. Looking through issues, I’ve seen a few other requests for enum based polymorphic type columns. Personally, I’m not a huge fan of inserting model names into the database: it just seems like an enum or table name would be more appropriate.

Is there a built-in way to use different values for the polymorphic type column? It seems like I can override ActiveRecord::Base.compute_type, but that’s kind of ugly.

I wrote up a monkey patch (using AR 4.0.13 and pretty much untested):

module ActiveRecord
module Associations
module BelongsToPolymorphicEnum
extend ActiveSupport::Concern

  included do
    alias_method_chain :klass, :enum
    alias_method_chain :replace_keys, :enum
  end

  def klass_with_enum
    if klass_types.nil?
      klass_without_enum
    else
      type = klass_types.invert[owner[reflection.foreign_type]]
      type.presence && type.constantize
    end
  end

  private

  def replace_keys_with_enum(record)
    if klass_types.nil?
      replace_keys_without_enum
    else
      super
      owner[reflection.foreign_type] = klass_types[record.class.name]
    end
  end

  def klass_types
    options[:types]
  end
end

module BuilderWithPolymorphicEnum
  def valid_options
    super + [:types]
  end
end

Builder::BelongsTo.send :include, BuilderWithPolymorphicEnum
BelongsToPolymorphicAssociation.send :include, BelongsToPolymorphicEnum

end
end

``

It allows you to do this:

class Picture < ActiveRecord::Base

belongs_to :imageable, polymorphic: true, types: { ‘Employee’ => 1, ‘Product’ => 2 }

end

``

I’m all for conventions, but Polymorphic tables seems like an area in need of more configuration options.