Skip to content

Instantly share code, notes, and snippets.

@kirel
Last active April 25, 2017 09:54
Show Gist options
  • Save kirel/7597979 to your computer and use it in GitHub Desktop.
Save kirel/7597979 to your computer and use it in GitHub Desktop.
Build correct sti subclass
# STI subclass building backported from Rails 4 to use in Rails 3.2 - see
# https://github.com/rails/rails/commit/89b5b31cc4f8407f648a2447665ef23f9024e8a5
# Usage:
# include BuildStiSubclass # in your model and be done
module BuildStiSubclass
extend ActiveSupport::Concern
included do
attr_accessible inheritance_column
end
module ClassMethods
# Determines if one of the attributes passed in is the inheritance column,
# and if the inheritance column is attr accessible, it initializes an
# instance of the given subclass instead of the base class
def new(*args, &block)
if (attrs = args.first).is_a?(Hash)
if subclass = subclass_from_attrs(attrs)
return subclass.new(*args, &block)
end
end
# Delegate to the original .new
super
end
# Detect the subclass from the inheritance column of attrs. If the inheritance column value
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
# If this is a StrongParameters hash, and access to inheritance_column is not permitted,
# this will ignore the inheritance column and return nil
def subclass_from_attrs(attrs)
subclass_name = attrs.with_indifferent_access[inheritance_column]
return nil if subclass_name.blank? || subclass_name == self.name
unless subclass = subclasses.detect { |sub| sub.name == subclass_name }
raise ActiveRecord::SubclassNotFound.new("Invalid single-table inheritance type: #{subclass_name} is not a subclass of #{name}")
end
subclass
end
end
end
@skorth
Copy link

skorth commented Nov 22, 2013

👍 Nice one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment