class Audited::Audit

def self.as_user(user, &block)

for background operations that require audit information.
by +user+. This method is hopefully threadsafe, making it ideal
All audits made during the block called will be recorded as made
def self.as_user(user, &block)
  ::Audited.store[:audited_user] = user
  yield
ensure
  ::Audited.store[:audited_user] = nil
end

def self.assign_revision_attributes(record, attributes)

Other tags:
    Private: -
def self.assign_revision_attributes(record, attributes)
  attributes.each do |attr, val|
    record = record.dup if record.frozen?
    if record.respond_to?("#{attr}=")
      record.attributes.key?(attr.to_s) ?
        record[attr] = val :
        record.send("#{attr}=", val)
    end
  end
  record
end

def self.audited_classes

Returns the list of classes that are being audited
def self.audited_classes
  audited_class_names.map(&:constantize)
end

def self.collection_cache_key(collection = all, timestamp_column = :created_at)

use created_at as timestamp cache key
def self.collection_cache_key(collection = all, timestamp_column = :created_at)
  super(collection, :created_at)
end

def self.reconstruct_attributes(audits)

Other tags:
    Private: -
def self.reconstruct_attributes(audits)
  attributes = {}
  result = audits.collect do |audit|
    attributes.merge!(audit.new_attributes)[:version] = audit.version
    yield attributes if block_given?
  end
  block_given? ? result : attributes
end

def ancestors

Return all audits older than the current one.
def ancestors
  self.class.ascending.auditable_finder(auditable_id, auditable_type).to_version(version)
end

def new_attributes

Returns a hash of the changed attributes with the new values
def new_attributes
  (audited_changes || {}).inject({}.with_indifferent_access) do |attrs, (attr, values)|
    attrs[attr] = values.is_a?(Array) ? values.last : values
    attrs
  end
end

def old_attributes

Returns a hash of the changed attributes with the old values
def old_attributes
  (audited_changes || {}).inject({}.with_indifferent_access) do |attrs, (attr, values)|
    attrs[attr] = Array(values).first
    attrs
  end
end

def revision

the object has been destroyed, this will be a new record.
Return an instance of what the object looked like at this revision. If
def revision
  clazz = auditable_type.constantize
  (clazz.find_by_id(auditable_id) || clazz.new).tap do |m|
    self.class.assign_revision_attributes(m, self.class.reconstruct_attributes(ancestors).merge(version: version))
  end
end

def set_audit_user

def set_audit_user
  self.user ||= ::Audited.store[:audited_user] # from .as_user
  self.user ||= ::Audited.store[:current_user].try!(:call) # from Sweeper
  nil # prevent stopping callback chains
end

def set_remote_address

def set_remote_address
  self.remote_address ||= ::Audited.store[:current_remote_address]
end

def set_request_uuid

def set_request_uuid
  self.request_uuid ||= ::Audited.store[:current_request_uuid]
  self.request_uuid ||= SecureRandom.uuid
end

def set_version_number

def set_version_number
  max = self.class.auditable_finder(auditable_id, auditable_type).descending.first.try(:version) || 0
  self.version = max + 1
end

def undo

Allows user to undo changes
def undo
  model = self.auditable_type.constantize
  if action == 'create'
    # destroys a newly created record
    model.find(auditable_id).destroy!
  elsif action == 'destroy'
    # creates a new record with the destroyed record attributes
    model.create(audited_changes)
  else
    # changes back attributes
    audited_object = model.find(auditable_id)
    self.audited_changes.each do |k, v|
      audited_object[k] = v[0]
    end
    audited_object.save
  end
end

def user_as_string

Other tags:
    Private: -
def user_as_string
  user_as_model || username
end

def user_as_string=(user)

Other tags:
    Private: -
def user_as_string=(user)
  # reset both either way
  self.user_as_model = self.username = nil
  user.is_a?(::ActiveRecord::Base) ?
    self.user_as_model = user :
    self.username = user
end