module PaperTrailAssociationTracking::RecordTrail

def add_transaction_id_to(data)

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

def appear_as_new_record

Other tags:
    Api: - private
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

def data_for_create

Other tags:
    Api: - private
def data_for_create
  data = super
  add_transaction_id_to(data)
  data
end

def data_for_destroy

Other tags:
    Api: - private
def data_for_destroy
  data = super
  add_transaction_id_to(data)
  data
end

def data_for_update(*args)

Other tags:
    Api: - private
def data_for_update(*args)
  data = super
  add_transaction_id_to(data)
  data
end

def data_for_update_columns(*args)

Other tags:
    Api: - private
def data_for_update_columns(*args)
  data = super
  add_transaction_id_to(data)
  data
end

def habtm_assoc_ids(habtm_assoc)

Other tags:
    Api: - private
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

def record_create

Other tags:
    Api: - private
def record_create
  version = super
  if version
    update_transaction_id(version)
    save_associations(version)
  end
end

def record_destroy(*args)

Other tags:
    Api: - private
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

def record_object_changes?

Other tags:
    Api: - private
def record_object_changes?
  @record.paper_trail_options[:save_changes] &&
    @record.class.paper_trail.version_class.column_names.include?("object_changes")
end

def record_update(**opts)

Other tags:
    Api: - private
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

def record_update_columns(*args)

Other tags:
    Api: - private
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

def save_associations(version)

Saves associations if the join table for `VersionAssociation` exists.
def save_associations(version)
  return unless ::PaperTrail.config.track_associations?
  save_bt_associations(version)
  save_habtm_associations(version)
end

def save_bt_association(assoc, version)

Other tags:
    Api: - private
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.present? && ::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)
    @record.class.paper_trail.version_association_class.create(assoc_version_args)
  end
end

def save_bt_associations(version)

Other tags:
    Api: - private
def save_bt_associations(version)
  @record.class.reflect_on_all_associations(:belongs_to).each do |assoc|
    save_bt_association(assoc, version)
  end
end

def save_habtm_association?(assoc)

Other tags:
    Api: - private
def save_habtm_association?(assoc)
  @record.class.paper_trail_save_join_tables.include?(assoc.name) ||
    ::PaperTrail.request.enabled_for_model?(assoc.klass)
end

def save_habtm_associations(version)

Other tags:
    Api: - private
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|
      @record.class.paper_trail.version_association_class.create(
        version_id: version.transaction_id,
        foreign_key_name: a.name,
        foreign_key_id: id,
        foreign_type: a.klass
      )
    end
  end
end

def update_transaction_id(version)

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