module Audited::Auditor::AuditedInstanceMethods
Public Instance Methods
audited_attributes()
click to toggle source
List of attributes that are audited.
# File lib/audited/auditor.rb, line 169 def audited_attributes audited_attributes = attributes.except(*self.class.non_audited_columns) normalize_enum_changes(audited_attributes) end
combine_audits(audits_to_combine)
click to toggle source
Combine multiple audits into one.
# File lib/audited/auditor.rb, line 183 def combine_audits(audits_to_combine) combine_target = audits_to_combine.last combine_target.audited_changes = audits_to_combine.pluck(:audited_changes).reduce(&:merge) combine_target.comment = "#{combine_target.comment}\nThis audit is the result of multiple audits being combined." transaction do combine_target.save! audits_to_combine.unscope(:limit).where("version < ?", combine_target.version).delete_all end end
method_missing(method_name, *args, &block)
click to toggle source
Deprecate version attribute in favor of audit_version attribute – preparing for eventual removal.
Calls superclass method
# File lib/audited/auditor.rb, line 94 def method_missing(method_name, *args, &block) if method_name == :version ActiveSupport::Deprecation.warn("`version` attribute has been changed to `audit_version`. This attribute will be removed.") audit_version else super end end
own_and_associated_audits()
click to toggle source
Returns a list combined of record audits and associated audits.
# File lib/audited/auditor.rb, line 175 def own_and_associated_audits Audited.audit_class.unscoped .where('(auditable_type = :type AND auditable_id = :id) OR (associated_type = :type AND associated_id = :id)', type: self.class.name, id: id) .order(created_at: :desc) end
revision(version)
click to toggle source
Get a specific revision specified by the version number, or :previous
Returns nil for versions greater than revisions count
# File lib/audited/auditor.rb, line 156 def revision(version) if version == :previous || self.audits.last.version >= version revision_with Audited.audit_class.reconstruct_attributes(audits_to(version)) end end
revision_at(date_or_time)
click to toggle source
Find the oldest revision recorded prior to the date/time provided.
# File lib/audited/auditor.rb, line 163 def revision_at(date_or_time) audits = self.audits.up_until(date_or_time) revision_with Audited.audit_class.reconstruct_attributes(audits) unless audits.empty? end
revisions(from_version = 1)
click to toggle source
Gets an array of the revisions available
user.revisions.each do |revision| user.name user.version end
# File lib/audited/auditor.rb, line 140 def revisions(from_version = 1) return [] unless audits.from_version(from_version).exists? all_audits = audits.select([:audited_changes, :version]).to_a targeted_audits = all_audits.select { |audit| audit.version >= from_version } previous_attributes = reconstruct_attributes(all_audits - targeted_audits) targeted_audits.map do |audit| previous_attributes.merge!(audit.new_attributes) revision_with(previous_attributes.merge!(version: audit.version)) end end
save_with_auditing()
click to toggle source
Temporarily turns on auditing while saving.
# File lib/audited/auditor.rb, line 119 def save_with_auditing with_auditing { save } end
save_without_auditing()
click to toggle source
Temporarily turns off auditing while saving.
# File lib/audited/auditor.rb, line 104 def save_without_auditing without_auditing { save } end
with_auditing(&block)
click to toggle source
Executes the block with the auditing callbacks enabled.
@foo.with_auditing do @foo.save end
# File lib/audited/auditor.rb, line 129 def with_auditing(&block) self.class.with_auditing(&block) end
without_auditing(&block)
click to toggle source
Executes the block with the auditing callbacks disabled.
@foo.without_auditing do @foo.save end
# File lib/audited/auditor.rb, line 114 def without_auditing(&block) self.class.without_auditing(&block) end
Protected Instance Methods
revision_with(attributes)
click to toggle source
# File lib/audited/auditor.rb, line 196 def revision_with(attributes) dup.tap do |revision| revision.id = id revision.send :instance_variable_set, '@new_record', destroyed? revision.send :instance_variable_set, '@persisted', !destroyed? revision.send :instance_variable_set, '@readonly', false revision.send :instance_variable_set, '@destroyed', false revision.send :instance_variable_set, '@_destroyed', false revision.send :instance_variable_set, '@marked_for_destruction', false Audited.audit_class.assign_revision_attributes(revision, attributes) # Remove any association proxies so that they will be recreated # and reference the correct object for this revision. The only way # to determine if an instance variable is a proxy object is to # see if it responds to certain methods, as it forwards almost # everything to its target. revision.instance_variables.each do |ivar| proxy = revision.instance_variable_get ivar if !proxy.nil? && proxy.respond_to?(:proxy_respond_to?) revision.instance_variable_set ivar, nil end end end end
Private Instance Methods
audit_create()
click to toggle source
# File lib/audited/auditor.rb, line 268 def audit_create write_audit(action: 'create', audited_changes: audited_attributes, comment: audit_comment) end
audit_destroy()
click to toggle source
# File lib/audited/auditor.rb, line 280 def audit_destroy write_audit(action: 'destroy', audited_changes: audited_attributes, comment: audit_comment) unless new_record? end
audit_update()
click to toggle source
# File lib/audited/auditor.rb, line 273 def audit_update unless (changes = audited_changes).empty? && (audit_comment.blank? || audited_options[:update_with_comment_only] == false) write_audit(action: 'update', audited_changes: changes, comment: audit_comment) end end
audited_changes()
click to toggle source
# File lib/audited/auditor.rb, line 223 def audited_changes all_changes = respond_to?(:changes_to_save) ? changes_to_save : changes filtered_changes = \ if audited_options[:only].present? all_changes.slice(*self.class.audited_columns) else all_changes.except(*self.class.non_audited_columns) end filtered_changes = normalize_enum_changes(filtered_changes) filtered_changes.to_hash end
auditing_enabled()
click to toggle source
# File lib/audited/auditor.rb, line 330 def auditing_enabled return run_conditional_check(audited_options[:if]) && run_conditional_check(audited_options[:unless], matching: false) && self.class.auditing_enabled end
audits_to(version = nil)
click to toggle source
# File lib/audited/auditor.rb, line 256 def audits_to(version = nil) if version == :previous version = if self.audit_version self.audit_version - 1 else previous = audits.descending.offset(1).first previous ? previous.version : 1 end end audits.to_version(version) end
combine_audits_if_needed()
click to toggle source
# File lib/audited/auditor.rb, line 310 def combine_audits_if_needed max_audits = audited_options[:max_audits] if max_audits && (extra_count = audits.count - max_audits) > 0 audits_to_combine = audits.limit(extra_count + 1) combine_audits(audits_to_combine) end end
comment_required_state?()
click to toggle source
# File lib/audited/auditor.rb, line 304 def comment_required_state? auditing_enabled && ((audited_options[:on].include?(:create) && self.new_record?) || (audited_options[:on].include?(:update) && self.persisted? && self.changed?)) end
normalize_enum_changes(changes)
click to toggle source
# File lib/audited/auditor.rb, line 236 def normalize_enum_changes(changes) self.class.defined_enums.each do |name, values| if changes.has_key?(name) changes[name] = \ if changes[name].is_a?(Array) changes[name].map { |v| values[v] } elsif rails_below?('5.0') changes[name] else values[changes[name]] end end end changes end
presence_of_audit_comment()
click to toggle source
# File lib/audited/auditor.rb, line 298 def presence_of_audit_comment if comment_required_state? errors.add(:audit_comment, "Comment can't be blank!") unless audit_comment.present? end end
rails_below?(rails_version)
click to toggle source
# File lib/audited/auditor.rb, line 252 def rails_below?(rails_version) Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new(rails_version) end
reconstruct_attributes(audits)
click to toggle source
# File lib/audited/auditor.rb, line 344 def reconstruct_attributes(audits) attributes = {} audits.each { |audit| attributes.merge!(audit.new_attributes) } attributes end
require_comment()
click to toggle source
# File lib/audited/auditor.rb, line 318 def require_comment if auditing_enabled && audit_comment.blank? errors.add(:audit_comment, "Comment can't be blank!") return false if Rails.version.start_with?('4.') throw(:abort) end end
run_conditional_check(condition, matching: true)
click to toggle source
# File lib/audited/auditor.rb, line 336 def run_conditional_check(condition, matching: true) return true if condition.blank? return condition.call(self) == matching if condition.respond_to?(:call) return send(condition) == matching if respond_to?(condition.to_sym, true) true end
write_audit(attrs)
click to toggle source
# File lib/audited/auditor.rb, line 285 def write_audit(attrs) attrs[:associated] = send(audit_associated_with) unless audit_associated_with.nil? self.audit_comment = nil if auditing_enabled run_callbacks(:audit) { audit = audits.create(attrs) combine_audits_if_needed if attrs[:action] != 'create' audit } end end