How I do STI: Utilize descendent tracking and override model_name so they use the same URL helpers and parameters as their base class. Makes things like responders and form_for work as expected, while preserving things like to_partial_path.
class RecordsController < ApplicationController
before_filter :prepare_records
before_filter :prepare_record, only: [:show, :edit, :update, :destroy]
respond_to :html, :json
def new
respond_with @record = Record[params.require(:type)].new
end
def create
respond_with @record = Record[params.require(:record_type)].create(record_params)
end
def show
respond_with @record
end
def edit
respond_with @record
end
def update
@record.update_attributes(record_params)
respond_with @record
end
def destroy
@record.destroy
respond_with @record
end
private
def prepare_records
@records = Record.scoped
end
def prepare_record
@record = @records.find(params[:id])
end
def record_params
params.require(:record).permit(:name, :content)
end
end
class Record < ActiveRecord::Base
extend InheritenceBaseNaming
def [] type
descendents.find { |descendent| descendent.name == type }
end
end
class OrangeRecord < Record
end
module InheritenceBaseNaming
def model_name
@_model_name ||= super.tap do |name|
unless self == base_class
the_base_class = base_class
%w(param_key singular_route_key route_key).each do |key|
name.singleton_class.send(:define_method, key) { the_base_class.model_name.public_send(key) }
end
end
end
end
end
class AppleRecord < Record
end