Module: Auditable::Auditing

Extended by:
ActiveSupport::Concern
Defined in:
lib/auditable/auditing.rb

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#audit_actionObject

INSTANCE METHODS



39
40
41
# File 'lib/auditable/auditing.rb', line 39

def audit_action
  @audit_action
end

#audit_tagObject

INSTANCE METHODS



39
40
41
# File 'lib/auditable/auditing.rb', line 39

def audit_tag
  @audit_tag
end

#changed_byObject

INSTANCE METHODS



39
40
41
# File 'lib/auditable/auditing.rb', line 39

def changed_by
  @changed_by
end

Instance Method Details

#audit_tag_with(tag) ⇒ Object

Mark the latest record with a tag in order to easily find and perform diff against later If there are no audits for this record, create a new audit with this tag



48
49
50
51
52
53
54
55
# File 'lib/auditable/auditing.rb', line 48

def audit_tag_with(tag)
  if last_audit
    last_audit.update_attribute(:tag, tag)
  else
    self.audit_tag = tag
    snap!
  end
end

#audited_changes(options = {}) ⇒ Object

Get the latest changes by comparing the latest two audits



84
85
86
# File 'lib/auditable/auditing.rb', line 84

def audited_changes(options = {})
  audits.last.try(:latest_diff, options) || {}
end

#last_auditObject

Get the latest audit record



42
43
44
# File 'lib/auditable/auditing.rb', line 42

def last_audit
  audits.last
end

#last_change_of(attribute) ⇒ Object

Return last attribute’s change

This method may be slow and inefficient on model with lots of audit objects. Go through each audit in the reverse order and find the first occurrence when audit.modifications changed



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/auditable/auditing.rb', line 93

def last_change_of(attribute)
  raise "#{attribute} is not audited for model #{self.class}. Audited attributes: #{self.class.audited_attributes}" unless self.class.audited_attributes.include? attribute.to_sym
  attribute = attribute.to_s # support symbol as well
  last = audits.size - 1
  last.downto(1) do |i|
    if audits[i].modifications[attribute] != audits[i-1].modifications[attribute]
      return audits[i].diff(audits[i-1])[attribute]
    end
  end
  nil
end

#snap!(options = {}) ⇒ Object

Take a snapshot of and save the current state of the audited record’s audited attributes

Accept values for :tag, :action and :user in the argument hash. However, these are overridden by the values set by the auditable record’s virtual attributes (#audit_tag, #audit_action, #changed_by) if defined



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/auditable/auditing.rb', line 60

def snap!(options = {})
  snap = {}.tap do |s|
    self.class.audited_attributes.each do |attr|
      s[attr.to_s] = self.send attr
    end
  end

  last_saved_audit = audits.last

  # build new audit
  audit = audits.build(options.merge :modifications => snap)
  audit.tag = self.audit_tag if audit_tag
  audit.action = self.audit_action if audit_action
  audit.changed_by = self.changed_by if changed_by

  # only save if it's different from before
  if !audit.same_audited_content?(last_saved_audit)
    audit.save
  else
    audits.delete(audit)
  end
end