public
Created — forked from shakerlxxv/sti_helpers.rb

To smooth out the use of STI for Rails models

  • Download Gist
sti_helpers.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#-------------------------------------------------------------------------------
# This module is meant to be included in the Base class of an STI model
# hierarchy.
#
# Heavily inspired by a couple key blog posts
# http://code.alexreisner.com/articles/single-table-inheritance-in-rails.html
# http://coderrr.wordpress.com/2008/04/22/building-the-right-class-with-sti-in-rails/#comment-1826
#
# Thanks to Alex and coderrr!
#-------------------------------------------------------------------------------
module StiHelpers
def self.included(base)
base.send :include, InstanceMethods
base.extend ClassMethods
end
 
module ClassMethods
 
def select_options
descendants.map{ |c| c.to_s }.sort
end
 
def inherited(child)
child.instance_eval do
def model_name
sti_base_class.model_name
end
end
super
end
 
def sti_base_class
if "#{self.superclass.name}" == "ActiveRecord::Base"
return self
end
return superclass.sti_base_class
end
 
# !! with the first conditional clause type logic will only apply to base class
# this MAY not be what you'd want, in which case ommit.
def new(*a, &b)
if (self == sti_base_class) and (h = a.first).is_a? Hash and (type = h[:type] || h['type']) and (klass = type.constantize) != self
raise "wtF hax!!" unless klass < self # klass should be a descendant of us
return klass.new(*a, &b)
end
super(*a, &b)
end
end
 
module InstanceMethods
def sti_base_class
self.class.sti_base_class
end
end
 
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.