module PaperTrailAssociationTracking::RecordTrail

Public Instance Methods

appear_as_new_record() { || ... } click to toggle source

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

> .. as best as I can tell, the purpose of > appear_as_new_record was to attempt to prevent the callbacks in > AutosaveAssociation (which is the module responsible for persisting > foreign key changes earlier than most people want most of the time > because backwards compatibility or the maintainer hates himself or > something) from running. By also stubbing out persisted? we can > actually prevent those. A more stable option might be to use suppress > instead, similar to the other branch in reify_has_one. > -Sean Griffin (github.com/paper-trail-gem/paper_trail/pull/899)

@api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 19
def appear_as_new_record
  @record.instance_eval {
    alias :old_new_record? :new_record?
    alias :new_record? :present?
    alias :old_persisted? :persisted?
    alias :persisted? :nil?
  }
  yield
  @record.instance_eval {
    alias :new_record? :old_new_record?
    alias :persisted? :old_persisted?
  }
end
data_for_create() click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 43
def data_for_create
  data = super
  add_transaction_id_to(data)
  data
end
data_for_destroy() click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 60
def data_for_destroy
  data = super
  add_transaction_id_to(data)
  data
end
data_for_update(*args) click to toggle source

Used during `record_update`, returns a hash of data suitable for an AR `create`. That is, all the attributes of the nascent `Version` record.

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 88
def data_for_update(*args)
  data = super
  add_transaction_id_to(data)
  data
end
data_for_update_columns(*args) click to toggle source

Returns data for record_update_columns @api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 106
def data_for_update_columns(*args)
  data = super
  add_transaction_id_to(data)
  data
end
record_create() click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 34
def record_create
  version = super
  if version
    update_transaction_id(version)
    save_associations(version)
  end
end
record_destroy(*args) click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 50
def record_destroy(*args)
  version = super
  if version && version.respond_to?(:errors) && version.errors.empty?
    update_transaction_id(version)
    save_associations(version)
  end
  version
end
record_object_changes?() click to toggle source

Returns a boolean indicating whether to store serialized version diffs in the `object_changes` column of the version record. @api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 69
def record_object_changes?
  @record.paper_trail_options[:save_changes] &&
    @record.class.paper_trail.version_class.column_names.include?("object_changes")
end
record_update(**opts) click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 75
def record_update(**opts)
  version = super
  if version && version.respond_to?(:errors) && version.errors.empty?
    update_transaction_id(version)
    save_associations(version)
  end
  version
end
record_update_columns(*args) click to toggle source

@api private

Calls superclass method
# File lib/paper_trail_association_tracking/record_trail.rb, line 95
def record_update_columns(*args)
  version = super
  if version && version.respond_to?(:errors) && version.errors.empty?
    update_transaction_id(version)
    save_associations(version)
  end
  version
end
save_associations(version) click to toggle source

Saves associations if the join table for `VersionAssociation` exists.

# File lib/paper_trail_association_tracking/record_trail.rb, line 113
def save_associations(version)
  return unless ::PaperTrail.config.track_associations?
  save_bt_associations(version)
  save_habtm_associations(version)
end
save_bt_associations(version) click to toggle source

Save all `belongs_to` associations. @api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 121
def save_bt_associations(version)
  @record.class.reflect_on_all_associations(:belongs_to).each do |assoc|
    save_bt_association(assoc, version)
  end
end
save_habtm_associations(version) click to toggle source

When a record is created, updated, or destroyed, we determine what the HABTM associations looked like before any changes were made, by using the `paper_trail_habtm` data structure. Then, we create `VersionAssociation` records for each of the associated records. @api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 132
def save_habtm_associations(version)
  @record.class.reflect_on_all_associations(:has_and_belongs_to_many).each do |a|
    next unless save_habtm_association?(a)
    habtm_assoc_ids(a).each do |id|
      ::PaperTrail::VersionAssociation.create(
        version_id: version.transaction_id,
        foreign_key_name: a.name,
        foreign_key_id: id,
        foreign_type: a.klass
      )
    end
  end
end

Private Instance Methods

add_transaction_id_to(data) click to toggle source
# File lib/paper_trail_association_tracking/record_trail.rb, line 148
def add_transaction_id_to(data)
  return unless @record.class.paper_trail.version_class.column_names.include?("transaction_id")
  data[:transaction_id] = ::PaperTrail.request.transaction_id
end
habtm_assoc_ids(habtm_assoc) click to toggle source

Given a HABTM association, returns an array of ids.

@api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 156
def habtm_assoc_ids(habtm_assoc)
  current = @record.send(habtm_assoc.name).to_a.map(&:id) # TODO: `pluck` would use less memory
  removed = @record.paper_trail_habtm.try(:[], habtm_assoc.name).try(:[], :removed) || []
  added = @record.paper_trail_habtm.try(:[], habtm_assoc.name).try(:[], :added) || []
  current + removed - added
end
save_bt_association(assoc, version) click to toggle source

Save a single `belongs_to` association. @api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 165
def save_bt_association(assoc, version)
  assoc_version_args = {
    version_id: version.id,
    foreign_key_name: assoc.foreign_key
  }

  if assoc.options[:polymorphic]
    foreign_type = @record.send(assoc.foreign_type)
    if foreign_type && ::PaperTrail.request.enabled_for_model?(foreign_type.constantize)
      assoc_version_args[:foreign_key_id] = @record.send(assoc.foreign_key)
      assoc_version_args[:foreign_type] = foreign_type
    end
  elsif ::PaperTrail.request.enabled_for_model?(assoc.klass)
    assoc_version_args[:foreign_key_id] = @record.send(assoc.foreign_key)
    assoc_version_args[:foreign_type] = assoc.klass
  end

  if assoc_version_args.key?(:foreign_key_id)
    ::PaperTrail::VersionAssociation.create(assoc_version_args)
  end
end
save_habtm_association?(assoc) click to toggle source

Returns true if the given HABTM association should be saved. @api private

# File lib/paper_trail_association_tracking/record_trail.rb, line 189
def save_habtm_association?(assoc)
  @record.class.paper_trail_save_join_tables.include?(assoc.name) ||
    ::PaperTrail.request.enabled_for_model?(assoc.klass)
end
update_transaction_id(version) click to toggle source
# File lib/paper_trail_association_tracking/record_trail.rb, line 194
def update_transaction_id(version)
  return unless @record.class.paper_trail.version_class.column_names.include?("transaction_id")
  if ::PaperTrail.transaction? && ::PaperTrail.request.transaction_id.nil?
    ::PaperTrail.request.transaction_id = version.id
    version.transaction_id = version.id
    version.save
  end
end