Module: ChronoModel::TimeMachine::HistoryMethods

Includes:
TimeQuery
Defined in:
lib/chrono_model/time_machine.rb

Overview

Methods that make up the history interface of the companion History model, automatically built for each Model that includes TimeMachine

Instance Method Summary collapse

Instance Method Details

#as_of(time) ⇒ Object

Fetches as of time records.



492
493
494
# File 'lib/chrono_model/time_machine.rb', line 492

def as_of(time)
  non_history_superclass.from(virtual_table_at(time)).as_of_time!(time)
end

#at(time) ⇒ Object

Fetches history record at the given time



505
506
507
# File 'lib/chrono_model/time_machine.rb', line 505

def at(time)
  time_query(:at, time).from(quoted_table_name).as_of_time!(time)
end

#force_history_fieldsObject

FIXME Remove, this was a workaround to a former design flaw.

- vjt  Wed Oct 28 17:13:57 CET 2015


528
529
530
# File 'lib/chrono_model/time_machine.rb', line 528

def force_history_fields
  self
end

#history?Boolean

To identify this class as the History subclass

Returns:

  • (Boolean)


467
468
469
# File 'lib/chrono_model/time_machine.rb', line 467

def history?
  true
end

#non_history_superclass(klass = self) ⇒ Object

Getting the correct quoted_table_name can be tricky when STI is involved. If Orange < Fruit, then Orange::History < Fruit::History (see define_inherited_history_model_for). This means that the superclass method returns Fruit::History, which will give us the wrong table name. What we actually want is the superclass of Fruit::History, which is Fruit. So, we use non_history_superclass instead. -npj



478
479
480
481
482
483
484
# File 'lib/chrono_model/time_machine.rb', line 478

def non_history_superclass(klass = self)
  if klass.superclass.history?
    non_history_superclass(klass.superclass)
  else
    klass.superclass
  end
end

#of(object) ⇒ Object

Fetches the given object history, sorted by history record time by default. Always includes an “as_of_time” column that is either the upper bound of the validity range or now() if history validity is maximum.



520
521
522
# File 'lib/chrono_model/time_machine.rb', line 520

def of(object)
  where(:id => object)
end

#pastObject



462
463
464
# File 'lib/chrono_model/time_machine.rb', line 462

def past
  time_query(:before, :now).where("NOT upper_inf(#{quoted_table_name}.validity)")
end

#quoted_history_fieldsObject



610
611
612
613
614
615
616
617
618
619
# File 'lib/chrono_model/time_machine.rb', line 610

def quoted_history_fields
  @quoted_history_fields ||= begin
    validity =
      [connection.quote_table_name(table_name),
       connection.quote_column_name('validity')
      ].join('.')

    [:lower, :upper].map! {|func| "#{func}(#{validity})"}
  end
end

#relationObject



486
487
488
# File 'lib/chrono_model/time_machine.rb', line 486

def relation
  super.as_of_time!(Time.now)
end

#sortedObject

Returns the history sorted by recorded_at



511
512
513
# File 'lib/chrono_model/time_machine.rb', line 511

def sorted
  all.order(%[ #{quoted_table_name}."recorded_at", #{quoted_table_name}."hid" ])
end

#time_query(match, time, options = {}) ⇒ Object

In the History context, pre-fill the :on options with the validity interval.



457
458
459
460
# File 'lib/chrono_model/time_machine.rb', line 457

def time_query(match, time, options = {})
  options[:on] ||= :validity
  super
end

#virtual_table_at(time, name = nil) ⇒ Object



496
497
498
499
500
501
# File 'lib/chrono_model/time_machine.rb', line 496

def virtual_table_at(time, name = nil)
  name = name ? connection.quote_table_name(name) :
    non_history_superclass.quoted_table_name

  "(#{at(time).to_sql}) #{name}"
end