Fixing STI in Rails 3.2

Rails 3.2 does not handle building STI classes by saving the :type. There are a handful of solutions for fixing it, but they all break building through relationships because they don't handle blocks. This fixes that limitation.

Place the following code in an initializer: /config/initializers/active_record_sti_patch.rb

if Rails.version > '3.2' && Rails.version < '4'
  class ActiveRecord::Reflection::AssociationReflection
    def build_association(*opts, &block)
      col = klass.inheritance_column.to_sym
      if (h = opts.first).is_a? Hash and (type = h.symbolize_keys[col]) and (type.class == Class || type.class == String)
        opts.first.with_indifferent_access[col].to_s.constantize.new(*opts, &block)
      elsif klass.abstract_class?
        raise "#{klass.to_s} is an abstract class and can not be directly instantiated"
      else
        klass.new(*opts, &block)
      end
    end
  end
end


Updated June 16th, 2016:
Added support for the passed in attributes hash keys to be either strings or symbols.