Module: PaperTrail::Model::InstanceMethods

Defined in:
lib/paper_trail/has_paper_trail.rb

Overview

Wrap the following methods in a module so we can include them only in the ActiveRecord models that declare `has_paper_trail`.

Instance Method Summary collapse

Instance Method Details

#appear_as_new_recordObject

Utility method for reifying. Anything executed inside the block will appear like a new record



250
251
252
253
254
255
256
257
# File 'lib/paper_trail/has_paper_trail.rb', line 250

def appear_as_new_record
  instance_eval {
    alias :old_new_record? :new_record?
    alias :new_record? :present?
  }
  yield
  instance_eval { alias :new_record? :old_new_record? }
end

#clear_rolled_back_versionsObject

Invoked after rollbacks to ensure versions records are not created for changes that never actually took place



201
202
203
# File 'lib/paper_trail/has_paper_trail.rb', line 201

def clear_rolled_back_versions
  send(self.class.versions_association_name).reload
end

#live?Boolean

Returns true if this instance is the current, live one; returns false if this instance came from a previous version.



185
186
187
# File 'lib/paper_trail/has_paper_trail.rb', line 185

def live?
  source_version.nil?
end

#next_versionObject

Returns the object (not a Version) as it became next. NOTE: if self (the item) was not reified from a version, i.e. it is the

"live" item, we return nil.  Perhaps we should return self instead?


229
230
231
232
233
234
# File 'lib/paper_trail/has_paper_trail.rb', line 229

def next_version
  subsequent_version = source_version.next
  subsequent_version ? subsequent_version.reify : self.class.find(self.id)
rescue
  nil
end

#originatorObject



194
195
196
197
# File 'lib/paper_trail/has_paper_trail.rb', line 194

def originator
  warn "DEPRECATED: use `paper_trail_originator` instead of `originator`. Support for `originator` will be removed in PaperTrail 4.0"
  self.paper_trail_originator
end

#paper_trail_enabled_for_model?Boolean



236
237
238
# File 'lib/paper_trail/has_paper_trail.rb', line 236

def paper_trail_enabled_for_model?
  self.class.paper_trail_enabled_for_model?
end

#paper_trail_originatorObject

Returns who put the object into its current state.



190
191
192
# File 'lib/paper_trail/has_paper_trail.rb', line 190

def paper_trail_originator
  (source_version || send(self.class.versions_association_name).last).try(:whodunnit)
end

#previous_versionObject

Returns the object (not a Version) as it was most recently.



221
222
223
224
# File 'lib/paper_trail/has_paper_trail.rb', line 221

def previous_version
  preceding_version = source_version ? source_version.previous : send(self.class.versions_association_name).last
  preceding_version.reify if preceding_version
end

#touch_with_version(name = nil) ⇒ Object

Mimicks behavior of `touch` method from `ActiveRecord::Persistence`, but generates a version

TODO: lookinto leveraging the `after_touch` callback from `ActiveRecord` to allow the

regular `touch` method go generate a version as normal. May make sense to switch the `record_update`
method to leverage an `after_update` callback anyways (likely for v4.0.0)

Raises:

  • (ActiveRecordError)


274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/paper_trail/has_paper_trail.rb', line 274

def touch_with_version(name = nil)
  raise ActiveRecordError, "can not touch on a new record object" unless persisted?

  attributes = timestamp_attributes_for_update_in_model
  attributes << name if name
  current_time = current_time_from_proper_timezone

  attributes.each { |column| write_attribute(column, current_time) }
  # ensure a version is written even if the `:on` collection is empty
  record_update(true) if paper_trail_options[:on] == []
  save!(:validate => false)
end

#version_at(timestamp, reify_options = {}) ⇒ Object

Returns the object (not a Version) as it was at the given timestamp.



206
207
208
209
210
211
212
# File 'lib/paper_trail/has_paper_trail.rb', line 206

def version_at(timestamp, reify_options={})
  # Because a version stores how its object looked *before* the change,
  # we need to look for the first version created *after* the timestamp.
  v = send(self.class.versions_association_name).subsequent(timestamp, true).first
  return v.reify(reify_options) if v
  self unless self.destroyed?
end

#versions_between(start_time, end_time, reify_options = {}) ⇒ Object

Returns the objects (not Versions) as they were between the given times.



215
216
217
218
# File 'lib/paper_trail/has_paper_trail.rb', line 215

def versions_between(start_time, end_time, reify_options={})
  versions = send(self.class.versions_association_name).between(start_time, end_time)
  versions.collect { |version| version_at(version.send PaperTrail.timestamp_field) }
end

#whodunnit(value) ⇒ Object

Temporarily overwrites the value of whodunnit and then executes the provided block.



260
261
262
263
264
265
266
267
# File 'lib/paper_trail/has_paper_trail.rb', line 260

def whodunnit(value)
  raise ArgumentError, 'expected to receive a block' unless block_given?
  current_whodunnit = PaperTrail.whodunnit
  PaperTrail.whodunnit = value
  yield self
ensure
  PaperTrail.whodunnit = current_whodunnit
end

#without_versioning(method = nil) ⇒ Object

Executes the given method or block without creating a new version.



241
242
243
244
245
246
247
# File 'lib/paper_trail/has_paper_trail.rb', line 241

def without_versioning(method = nil)
  paper_trail_was_enabled = self.paper_trail_enabled_for_model?
  self.class.paper_trail_off!
  method ? method.to_proc.call(self) : yield(self)
ensure
  self.class.paper_trail_on! if paper_trail_was_enabled
end