Created — forked from shakerlxxv/sti_helpers.rb

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

To smooth out the use of STI for Rails models

View sti_helpers.rb
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.