Module: ChronoModel::TimeMachine
- Extended by:
- ActiveSupport::Concern
- Includes:
- Patches::AsOfTimeHolder
- Defined in:
- lib/chrono_model/time_machine.rb,
lib/chrono_model/time_machine/timeline.rb,
lib/chrono_model/time_machine/time_query.rb,
lib/chrono_model/time_machine/history_model.rb
Defined Under Namespace
Modules: ClassMethods, HistoryModel, TimeQuery, Timeline
Class Method Summary collapse
Instance Method Summary collapse
-
#as_of(time) ⇒ Object
Returns a read-only representation of this record as it was
time
ago. -
#as_of!(time) ⇒ Object
Returns a read-only representation of this record as it was
time
ago. -
#changes_against(ref) ⇒ Object
Returns the differences between this record and an arbitrary reference record.
-
#current_version ⇒ Object
Returns the current history version.
-
#destroy ⇒ Object
Inhibit destroy of historical records.
-
#historical? ⇒ Boolean
Returns a boolean indicating whether this record is an history entry.
-
#history ⇒ Object
Return the complete read-only history of this instance.
-
#last_changes ⇒ Object
Returns the differences between this entry and the previous history one.
-
#pred(options = {}) ⇒ Object
Returns the previous record in the history, or nil if this is the only recorded entry.
-
#pred_timestamp(options = {}) ⇒ Object
Returns the previous timestamp in this record’s timeline.
-
#succ ⇒ Object
This is a current record, so its next instance is always nil.
-
#timeline(options = {}) ⇒ Object
Returns an Array of timestamps for which this instance has an history record.
Methods included from Patches::AsOfTimeHolder
Class Method Details
.define_history_model_for(model) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/chrono_model/time_machine.rb', line 75 def self.define_history_model_for(model) history = Class.new(model) do include ChronoModel::TimeMachine::HistoryModel end model.singleton_class.instance_eval do define_method(:history) { history } end model.const_set :History, history end |
Instance Method Details
#as_of(time) ⇒ Object
Returns a read-only representation of this record as it was time
ago. Returns nil if no record is found.
123 124 125 |
# File 'lib/chrono_model/time_machine.rb', line 123 def as_of(time) _as_of(time).first end |
#as_of!(time) ⇒ Object
Returns a read-only representation of this record as it was time
ago. Raises ActiveRecord::RecordNotFound if no record is found.
130 131 132 |
# File 'lib/chrono_model/time_machine.rb', line 130 def as_of!(time) _as_of(time).first! end |
#changes_against(ref) ⇒ Object
Returns the differences between this record and an arbitrary reference record. The changes representation is an hash keyed by attribute whose values are arrays containing previous and current attributes values - the same format used by ActiveModel::Dirty.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/chrono_model/time_machine.rb', line 226 def changes_against(ref) self.class.attribute_names_for_history_changes.inject({}) do |changes, attr| old = ref.public_send(attr) new = public_send(attr) changes.tap do |c| changed = if old.respond_to?(:history_eql?) !old.history_eql?(new) else old != new end c[attr] = [old, new] if changed end end end |
#current_version ⇒ Object
Returns the current history version
205 206 207 208 209 210 211 |
# File 'lib/chrono_model/time_machine.rb', line 205 def current_version if historical? self.class.find(id) else self end end |
#destroy ⇒ Object
Inhibit destroy of historical records
164 165 166 167 168 |
# File 'lib/chrono_model/time_machine.rb', line 164 def destroy raise ActiveRecord::ReadOnlyRecord, 'Cannot delete historical records' if historical? super end |
#historical? ⇒ Boolean
Returns a boolean indicating whether this record is an history entry.
158 159 160 |
# File 'lib/chrono_model/time_machine.rb', line 158 def historical? as_of_time.present? end |
#history ⇒ Object
Return the complete read-only history of this instance.
145 146 147 |
# File 'lib/chrono_model/time_machine.rb', line 145 def history self.class.history.chronological.of(self) end |
#last_changes ⇒ Object
Returns the differences between this entry and the previous history one. See: changes_against
.
216 217 218 219 |
# File 'lib/chrono_model/time_machine.rb', line 216 def last_changes pred = self.pred changes_against(pred) if pred end |
#pred(options = {}) ⇒ Object
Returns the previous record in the history, or nil if this is the only recorded entry.
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/chrono_model/time_machine.rb', line 173 def pred( = {}) if self.class.timeline_associations.empty? history.reverse_order.second else return nil unless (ts = ()) order_clause = Arel.sql %[ LOWER(#{[:table] || self.class.quoted_table_name}."validity") DESC ] self.class.as_of(ts).order(order_clause).find([:id] || id) end end |
#pred_timestamp(options = {}) ⇒ Object
Returns the previous timestamp in this record’s timeline. Includes temporal associations.
188 189 190 191 192 193 194 195 |
# File 'lib/chrono_model/time_machine.rb', line 188 def ( = {}) if historical? [:before] ||= as_of_time timeline(.merge(limit: 1, reverse: true)).first else timeline(.merge(limit: 2, reverse: true)).second end end |
#succ ⇒ Object
This is a current record, so its next instance is always nil.
199 200 201 |
# File 'lib/chrono_model/time_machine.rb', line 199 def succ nil end |
#timeline(options = {}) ⇒ Object
Returns an Array of timestamps for which this instance has an history record. Takes temporal associations into account.
152 153 154 |
# File 'lib/chrono_model/time_machine.rb', line 152 def timeline( = {}) self.class.history.timeline(self, ) end |