lib/track_history.rb
# Make a model historical
# Takes a hash of options, which can only be :model_name to force a different model name
# Default model name is ModelHistory
Make a model historical
Takes a hash of options, which can only be :model_name to force a different model name
Default model name is ModelHistory
Make a model historical Takes a hash of options which can only be : model_name to force a different model name Default model name is ModelHistory
def define_historical_model(base, model_name, table_name, track_reference, &block)
      model_name ||= "#{base.name}::History"
      class_path = model_name.split(/::/)
      inner_name = class_path.pop
      outer = class_path.inject(Object) { |outer, inner_name| outer.const_get(inner_name) }
      @klass_reference = outer.const_set(inner_name, Class.new(ActiveRecord::Base))
      @klass_reference.send(:table_name=, table_name) unless table_name.nil?
      unless @klass_reference.table_exists?
        $stderr.puts "[TrackHistory] No such table exists: #{@klass_reference.table_name} - #{self.name} history will not be tracked" unless TrackHistory.warnings_disabled?
        return
      end
      @klass_reference.send(:extend, TrackHistory::HistoryMethods)
      @klass_reference.instance_variable_set(:@historical_action_field, @klass_reference.columns_hash.has_key?('action') ? 'action' : nil)
      @klass_reference.instance_variable_set(:@track_historical_reference, track_reference)
      @klass_reference.module_eval(&block) if block_given?
      @klass_reference.columns_hash.each_key do |k|
        matches = k.match(/(.+?)_before$/)
        if matches && matches.size == 2 && field_name = matches[1]
          next if @klass_reference.historical_fields.has_key?(field_name) || @klass_reference.historical_tracks.has_key?(field_name) 
          @klass_reference.historical_fields[field_name] = { :before => "#{field_name}_before".to_sym, :after => "#{field_name}_after".to_sym }
        end
      end
      rel = base.name.singularize.underscore.downcase.to_sym
      @klass_reference.send(:include, TrackHistory::HistoricalRelationHelpers)
      if track_reference
        @klass_reference.belongs_to rel
        @klass_reference.send(:alias_method, :historical_relation, rel)
        has_many :histories, -> { order 'id desc' }, :class_name => model_name if track_reference
      end
      before_update :record_historical_changes
      unless @klass_reference.historical_action_field.nil?
        after_create :record_historical_changes_on_create
        before_destroy :record_historical_changes_on_destroy
      end
    end
def define_historical_model ( base , model_name , table_name , track_reference , & block ) model_name ||= "#{base.name}::History" class_path = model_name . split ( / :: / ) inner_name = class_path . pop outer = class_path . inject ( Object ) { | outer , inner_name | outer . const_get ( inner_name ) } @klass_reference = outer . const_set ( inner_name , Class . new ( ActiveRecord :: Base ) ) @klass_reference . send ( :table_name= , table_name ) unless table_name . nil? unless @klass_reference . table_exists? $stderr . puts "[TrackHistory] No such table exists: #{@klass_reference.table_name} - #{self.name} history will not be tracked" unless TrackHistory . warnings_disabled? return end @klass_reference . send ( :extend , TrackHistory :: HistoryMethods ) @klass_reference . instance_variable_set ( :@historical_action_field , @klass_reference . columns_hash . has_key? ( 'action' ) ? 'action' : nil ) @klass_reference . instance_variable_set ( :@track_historical_reference , track_reference ) @klass_reference . module_eval ( & block ) if block_given? @klass_reference . columns_hash . each_key do | k | matches = k . match ( / (.+?)_before$ / ) if matches && matches . size == 2 && field_name = matches [ 1 ] next if @klass_reference . historical_fields . has_key? ( field_name ) || @klass_reference . historical_tracks . has_key? ( field_name ) @klass_reference . historical_fields [ field_name ] = { :before => "#{field_name}_before" . to_sym , :after => "#{field_name}_after" . to_sym } end end rel = base . name . singularize . underscore . downcase . to_sym @klass_reference . send ( :include , TrackHistory :: HistoricalRelationHelpers ) if track_reference @klass_reference . belongs_to rel @klass_reference . send ( :alias_method , :historical_relation , rel ) has_many :histories , -> { order 'id desc' } , :class_name => model_name if track_reference end before_update :record_historical_changes unless @klass_reference . historical_action_field . nil? after_create :record_historical_changes_on_create before_destroy :record_historical_changes_on_destroy end end
Make a model historical
Takes a hash of options, which can only be :model_name to force a different model name
Default model name is ModelHistory
Make a model historical Takes a hash of options which can only be : model_name to force a different model name Default model name is ModelHistory
# figure out the model name # get the history class in line # figure out the field for tracking action (enum) # allow other things to be specified # infer fields # override inferrences # create the history class # create a backward reference # tell the other class about us # purposely don't define these until after getting historical_fields # track other things (optionally)
base
model_name
table_name
track_reference
block