Module: ChronoModel::TimeMachine::HistoryModel

Extended by:
ActiveSupport::Concern
Defined in:
lib/chrono_model/time_machine/history_model.rb

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#_find_record(options) ⇒ Object

ACTIVE RECORD 7 does not call ‘class.find` but a new internal method called `_find_record`



15
16
17
18
19
20
21
# File 'lib/chrono_model/time_machine/history_model.rb', line 15

def _find_record(options)
  if options && options[:lock]
    self.class.preload(strict_loaded_associations).lock(options[:lock]).find_by!(hid: hid)
  else
    self.class.preload(strict_loaded_associations).find_by!(hid: hid)
  end
end

#current_versionObject

Returns this history entry’s current record



203
204
205
# File 'lib/chrono_model/time_machine/history_model.rb', line 203

def current_version
  self.class.superclass.find(rid)
end

#firstObject

Returns the first history entry



191
192
193
# File 'lib/chrono_model/time_machine/history_model.rb', line 191

def first
  self.class.where(id: rid).chronological.first
end

#historical?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/chrono_model/time_machine/history_model.rb', line 158

def historical?
  true
end

#idObject

The history id is ‘hid`, but this cannot set as primary key or temporal associations will break. Solutions are welcome.



136
137
138
# File 'lib/chrono_model/time_machine/history_model.rb', line 136

def id
  hid
end

#lastObject

Returns the last history entry



197
198
199
# File 'lib/chrono_model/time_machine/history_model.rb', line 197

def last
  self.class.where(id: rid).chronological.last
end

#predObject

Returns the previous history entry, or nil if this is the first one.



165
166
167
168
169
170
171
172
173
# File 'lib/chrono_model/time_machine/history_model.rb', line 165

def pred
  return if valid_from.nil?

  if self.class.timeline_associations.empty?
    self.class.where('id = ? AND upper(validity) = ?', rid, valid_from).first
  else
    super(id: rid, before: valid_from, table: self.class.superclass.quoted_table_name)
  end
end

#read_attribute(attr_name, &block) ⇒ Object

Starting from Rails 6.0, ‘.read_attribute` will use the memoized `primary_key` if it detects that the attribute name is `id`.

Since the ‘primary key` may have been changed to `hid` because of `.find` overload, the new behavior may break relations where `id` is still the correct attribute to read

Ref: ifad/chronomodel#181



233
234
235
236
237
# File 'lib/chrono_model/time_machine/history_model.rb', line 233

def read_attribute(attr_name, &block)
  return super unless attr_name.to_s == 'id' && @primary_key.to_s == 'hid'

  _read_attribute('id', &block)
end

#ridObject

Referenced record ID.



142
143
144
# File 'lib/chrono_model/time_machine/history_model.rb', line 142

def rid
  attributes[self.class.primary_key]
end

#saveObject



146
147
148
# File 'lib/chrono_model/time_machine/history_model.rb', line 146

def save(*)
  with_hid_pkey { super }
end

#save!Object



150
151
152
# File 'lib/chrono_model/time_machine/history_model.rb', line 150

def save!(*)
  with_hid_pkey { super }
end

#succObject Also known as: next

Returns the next history entry, or nil if this is the last one.



178
179
180
181
182
183
184
185
186
# File 'lib/chrono_model/time_machine/history_model.rb', line 178

def succ
  return if valid_to.nil?

  if self.class.timeline_associations.empty?
    self.class.where('id = ? AND lower(validity) = ?', rid, valid_to).first
  else
    super(id: rid, after: valid_to, table: self.class.superclass.quoted_table_name)
  end
end

#update_columnsObject



154
155
156
# File 'lib/chrono_model/time_machine/history_model.rb', line 154

def update_columns(*)
  with_hid_pkey { super }
end

#valid_fromObject

Return ‘nil` instead of -Infinity/Infinity to preserve current Chronomodel behaviour and avoid failures with Rails 7.0 and unbounded time ranges

Check if ‘begin` and `end` are `Time` because validity is a `tsrange` column, so it is either `Time`, `nil`, and in some cases Infinity.

Ref: rails/rails#45099 TODO: consider removing when Rails 7.0 support will be dropped



216
217
218
# File 'lib/chrono_model/time_machine/history_model.rb', line 216

def valid_from
  validity.begin if validity.begin.is_a?(Time)
end

#valid_toObject Also known as: as_of_time



220
221
222
# File 'lib/chrono_model/time_machine/history_model.rb', line 220

def valid_to
  validity.end if validity.end.is_a?(Time)
end