Skip to content

Commit

Permalink
Define audit_class per model
Browse files Browse the repository at this point in the history
  • Loading branch information
kuldeepaggarwal committed Nov 28, 2022
1 parent 39d29e2 commit a7cd5f4
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 27 deletions.
42 changes: 25 additions & 17 deletions lib/audited/audit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,38 @@ module Audited
#

class YAMLIfTextColumnType
class << self
def load(obj)
if text_column?
ActiveRecord::Coders::YAMLColumn.new(Object).load(obj)
else
obj
end
end
def initialize(model)
@model = model
end

def dump(obj)
if text_column?
ActiveRecord::Coders::YAMLColumn.new(Object).dump(obj)
else
obj
end
def load(obj)
if text_column?
ActiveRecord::Coders::YAMLColumn.new(Object).load(obj)
else
obj
end
end

def text_column?
Audited.audit_class.columns_hash["audited_changes"].type.to_s == "text"
def dump(obj)
if text_column?
ActiveRecord::Coders::YAMLColumn.new(Object).dump(obj)
else
obj
end
end

private

def text_column?
@model.columns_hash["audited_changes"].type.to_s == "text"
end
end

class Audit < ::ActiveRecord::Base
def self.inherited(klass)
klass.serialize :audited_changes, YAMLIfTextColumnType.new(klass)
end

belongs_to :auditable, polymorphic: true
belongs_to :user, polymorphic: true
belongs_to :associated, polymorphic: true
Expand All @@ -49,7 +57,7 @@ class Audit < ::ActiveRecord::Base
cattr_accessor :audited_class_names
self.audited_class_names = Set.new

serialize :audited_changes, YAMLIfTextColumnType
serialize :audited_changes, YAMLIfTextColumnType.new(self)

scope :ascending, -> { reorder(version: :asc) }
scope :descending, -> { reorder(version: :desc) }
Expand Down
25 changes: 16 additions & 9 deletions lib/audited/auditor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ module Auditor #:nodoc:
CALLBACKS = [:audit_create, :audit_update, :audit_destroy]

module ClassMethods
def audit_class
audit_class_name&.safe_constantize || Audited.audit_class
end

# == Configuration options
#
#
Expand Down Expand Up @@ -67,20 +71,23 @@ def audited(options = {})

class_attribute :audit_associated_with, instance_writer: false
class_attribute :audited_options, instance_writer: false
class_attribute :audit_class_name, instance_writer: false

attr_accessor :audit_version, :audit_comment

self.audited_options = options
normalize_audited_options

self.audit_associated_with = audited_options[:associated_with]
self.audit_class_name = audited_options[:audit_class_name]

if audited_options[:comment_required]
validate :presence_of_audit_comment
before_destroy :require_comment if audited_options[:on].include?(:destroy)
end

has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name: Audited.audit_class.name, inverse_of: :auditable
Audited.audit_class.audited_class_names << to_s
has_many :audits, -> { order(version: :asc) }, as: :auditable, class_name: audit_class.name, inverse_of: :auditable
audit_class.audited_class_names << to_s

after_create :audit_create if audited_options[:on].include?(:create)
before_update :audit_update if audited_options[:on].include?(:update)
Expand All @@ -96,8 +103,8 @@ def audited(options = {})
enable_auditing
end

def has_associated_audits
has_many :associated_audits, as: :associated, class_name: Audited.audit_class.name
def has_associated_audits(audit_class_name: Audited.audit_class.name)
has_many :associated_audits, as: :associated, class_name: audit_class_name
end
end

Expand Down Expand Up @@ -159,14 +166,14 @@ def revisions(from_version = 1)
# Returns nil for versions greater than revisions count
def revision(version)
if version == :previous || audits.last.version >= version
revision_with Audited.audit_class.reconstruct_attributes(audits_to(version))
revision_with audit_class.reconstruct_attributes(audits_to(version))
end
end

# Find the oldest revision recorded prior to the date/time provided.
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?
revision_with audit_class.reconstruct_attributes(audits) unless audits.empty?
end

# List of attributes that are audited.
Expand All @@ -177,7 +184,7 @@ def audited_attributes

# Returns a list combined of record audits and associated audits.
def own_and_associated_audits
Audited.audit_class.unscoped
audit_class.unscoped
.where("(auditable_type = :type AND auditable_id = :id) OR (associated_type = :type AND associated_id = :id)",
type: self.class.base_class.name, id: id)
.order(created_at: :desc)
Expand Down Expand Up @@ -206,7 +213,7 @@ def revision_with(attributes)
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)
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
Expand Down Expand Up @@ -431,7 +438,7 @@ def enable_auditing
# convenience wrapper around
# @see Audit#as_user.
def audit_as(user, &block)
Audited.audit_class.as_user(user, &block)
audit_class.as_user(user, &block)
end

def auditing_enabled
Expand Down
2 changes: 1 addition & 1 deletion lib/audited/rspec_matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ def reflection
def association_exists?
!reflection.nil? &&
reflection.macro == :has_many &&
reflection.options[:class_name] == Audited.audit_class.name
reflection.options[:class_name] == model_class.audit_class.name
end
end
end
Expand Down

0 comments on commit a7cd5f4

Please sign in to comment.