eudaimonious
6/23/2013 - 4:58 AM

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

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