Module: Logidze::Model
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/logidze/model.rb
Overview
Extends model with methods to browse history
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- TIME_FACTOR =
Use this to convert Ruby time to milliseconds
1_000
Instance Attribute Summary collapse
-
#logidze_requested_ts ⇒ Object
Returns the value of attribute logidze_requested_ts.
Instance Method Summary collapse
-
#association(name) ⇒ Object
rubocop: disable Metrics/MethodLength.
-
#at(time: nil, version: nil) ⇒ Object
Return a dirty copy of record at specified time If time/version is less then the first version, then return nil.
-
#at!(time: nil, version: nil) ⇒ Object
Revert record to the version at specified time (without saving to DB).
-
#at_version(version) ⇒ Object
Return a dirty copy of specified version of record.
-
#at_version!(version) ⇒ Object
Revert record to the specified version (without saving to DB).
- #create_logidze_snapshot!(**opts) ⇒ Object
-
#diff_from(version: nil, time: nil) ⇒ Object
Return diff object representing changes since specified time.
-
#log_size ⇒ Object
rubocop: enable Metrics/MethodLength.
- #logidze_versions(reverse: false, include_self: false) ⇒ Object
- #raw_log_data ⇒ Object
-
#redo! ⇒ Object
Restore record to the future version (if ‘undo!` was applied) Return false if no future version found, otherwise return updated record.
-
#reload_log_data ⇒ Object
Loads log_data field from the database, stores to the attributes hash and returns it.
-
#reset_log_data ⇒ Object
Nullify log_data column for a single record.
-
#switch_to!(version, append: Logidze.append_on_undo) ⇒ Object
Restore record to the specified version.
-
#undo!(append: Logidze.append_on_undo) ⇒ Object
Restore record to the previous version.
Instance Attribute Details
#logidze_requested_ts ⇒ Object
Returns the value of attribute logidze_requested_ts.
85 86 87 |
# File 'lib/logidze/model.rb', line 85 def logidze_requested_ts @logidze_requested_ts end |
Instance Method Details
#association(name) ⇒ Object
rubocop: disable Metrics/MethodLength
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/logidze/model.rb', line 217 def association(name) association = super return association unless Logidze.associations_versioning should_apply_logidze = logidze_past? && association.klass.respond_to?(:has_logidze?) && !association.singleton_class.include?(Logidze::VersionedAssociation) return association unless should_apply_logidze association.singleton_class.prepend Logidze::VersionedAssociation if association.is_a? ActiveRecord::Associations::CollectionAssociation association.singleton_class.prepend( Logidze::VersionedAssociation::CollectionAssociation ) end association end |
#at(time: nil, version: nil) ⇒ Object
Return a dirty copy of record at specified time If time/version is less then the first version, then return nil. If time/version is greater then the last version, then return self. rubocop: disable Metrics/MethodLength
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/logidze/model.rb', line 91 def at(time: nil, version: nil) return at_version(version) if version time = parse_time(time) unless log_data return Logidze.return_self_if_log_data_is_empty ? self : nil end return nil unless log_data.exists_ts?(time) if log_data.current_ts?(time) self.logidze_requested_ts = time return self end log_entry = log_data.find_by_time(time) build_dup(log_entry, time) end |
#at!(time: nil, version: nil) ⇒ Object
Revert record to the version at specified time (without saving to DB)
128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/logidze/model.rb', line 128 def at!(time: nil, version: nil) return at_version!(version) if version raise ArgumentError, "#log_data is empty" unless log_data time = parse_time(time) return self if log_data.current_ts?(time) return false unless log_data.exists_ts?(time) version = log_data.find_by_time(time).version apply_diff(version, log_data.changes_to(version: version)) end |
#at_version(version) ⇒ Object
Return a dirty copy of specified version of record
144 145 146 147 148 149 150 151 152 |
# File 'lib/logidze/model.rb', line 144 def at_version(version) return nil unless log_data return self if log_data.version == version log_entry = log_data.find_by_version(version) return nil unless log_entry build_dup(log_entry) end |
#at_version!(version) ⇒ Object
Revert record to the specified version (without saving to DB)
155 156 157 158 159 160 161 162 |
# File 'lib/logidze/model.rb', line 155 def at_version!(version) raise ArgumentError, "#log_data is empty" unless log_data return self if log_data.version == version return false unless log_data.find_by_version(version) apply_diff(version, log_data.changes_to(version: version)) end |
#create_logidze_snapshot!(**opts) ⇒ Object
255 256 257 258 259 |
# File 'lib/logidze/model.rb', line 255 def create_logidze_snapshot!(**opts) self.class.where(self.class.primary_key => id).create_logidze_snapshot(**opts) reload_log_data end |
#diff_from(version: nil, time: nil) ⇒ Object
Return diff object representing changes since specified time.
170 171 172 173 174 175 176 177 178 179 |
# File 'lib/logidze/model.rb', line 170 def diff_from(version: nil, time: nil) time = parse_time(time) if time changes = log_data&.diff_from(time: time, version: version)&.tap do |v| deserialize_changes!(v) end || {} changes.delete_if { |k, _v| deleted_column?(k) } {"id" => id, "changes" => changes} end |
#log_size ⇒ Object
rubocop: enable Metrics/MethodLength
241 242 243 |
# File 'lib/logidze/model.rb', line 241 def log_size log_data&.size || 0 end |
#logidze_versions(reverse: false, include_self: false) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/logidze/model.rb', line 112 def logidze_versions(reverse: false, include_self: false) = log_data.versions.dup if reverse .reverse! .shift unless include_self else .pop unless include_self end Enumerator.new { |yielder| .each { yielder << at(version: _1.version) } } end |
#raw_log_data ⇒ Object
261 262 263 |
# File 'lib/logidze/model.rb', line 261 def raw_log_data read_attribute_before_type_cast(:log_data) end |
#redo! ⇒ Object
Restore record to the future version (if ‘undo!` was applied) Return false if no future version found, otherwise return updated record.
192 193 194 195 196 197 |
# File 'lib/logidze/model.rb', line 192 def redo! version = log_data.next_version return false if version.nil? switch_to!(version.version) end |
#reload_log_data ⇒ Object
Loads log_data field from the database, stores to the attributes hash and returns it
246 247 248 |
# File 'lib/logidze/model.rb', line 246 def reload_log_data self.log_data = self.class.where(self.class.primary_key => id).pluck(:"#{self.class.table_name}.log_data").first end |
#reset_log_data ⇒ Object
Nullify log_data column for a single record
251 252 253 |
# File 'lib/logidze/model.rb', line 251 def reset_log_data self.class.without_logging { update_column(:log_data, nil) } end |
#switch_to!(version, append: Logidze.append_on_undo) ⇒ Object
Restore record to the specified version. Return false if version is unknown.
201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/logidze/model.rb', line 201 def switch_to!(version, append: Logidze.append_on_undo) raise ArgumentError, "#log_data is empty" unless log_data return false unless at_version(version) if append && version < log_version changes = log_data.changes_to(version: version) changes.each { |c, v| changes[c] = deserialize_value(c, v) } update!(changes) else at_version!(version) self.class.without_logging { save! } end end |
#undo!(append: Logidze.append_on_undo) ⇒ Object
Restore record to the previous version. Return false if no previous version found, otherwise return updated record.
183 184 185 186 187 188 |
# File 'lib/logidze/model.rb', line 183 def undo!(append: Logidze.append_on_undo) version = log_data.previous_version return false if version.nil? switch_to!(version.version, append: append) end |