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.


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

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


509
510
511
# File 'lib/chrono_model/time_machine.rb', line 509

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

532
533
534
# File 'lib/chrono_model/time_machine.rb', line 532

def force_history_fields
  self
end

#history?Boolean

To identify this class as the History subclass

Returns:

  • (Boolean)

471
472
473
# File 'lib/chrono_model/time_machine.rb', line 471

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


482
483
484
485
486
487
488
# File 'lib/chrono_model/time_machine.rb', line 482

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.


524
525
526
# File 'lib/chrono_model/time_machine.rb', line 524

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

#pastObject


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

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

#quoted_history_fieldsObject


614
615
616
617
618
619
620
621
622
623
# File 'lib/chrono_model/time_machine.rb', line 614

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


490
491
492
# File 'lib/chrono_model/time_machine.rb', line 490

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

#sortedObject

Returns the history sorted by recorded_at


515
516
517
# File 'lib/chrono_model/time_machine.rb', line 515

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.


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

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

#virtual_table_at(time, name = nil) ⇒ Object


500
501
502
503
504
505
# File 'lib/chrono_model/time_machine.rb', line 500

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