Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,24 @@ Audited.config do |config|
end
```

### Multiple `Audit` models

If you want to use a different audit model for a specfic audited model, create a new class that
inherits from `Audited::Audit`:
```ruby
class CustomAudit < Audited::Audit
def some_custom_behavior
"Hiya!"
end
end
```
Then provide the class name in options:
```ruby
class User < ActiveRecord::Base
audited class_name: "CustomAudit"
end
```

### Enum Storage

In 4.10, the default behavior for enums changed from storing the value synthesized by Rails to the value stored in the DB. You can restore the previous behavior by setting the store_synthesized_enums configuration value:
Expand Down
9 changes: 8 additions & 1 deletion lib/audited.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,20 @@ class << self
:store_synthesized_enums
attr_writer :audit_class

def audit_class
def default_audit_class
# The audit_class is set as String in the initializer. It can not be constantized during initialization and must
# be constantized at runtime. See https://github.com/collectiveidea/audited/issues/608
@audit_class = @audit_class.safe_constantize if @audit_class.is_a?(String)
@audit_class ||= Audited::Audit
end

def audit_class(custom_class_name = nil)
if custom_class_name.is_a?(String)
return custom_class_name.safe_constantize || default_audit_class
end
default_audit_class
end

# remove audit_model in next major version it was only shortly present in 5.1.0
alias_method :audit_model, :audit_class
deprecate audit_model: "use Audited.audit_class instead of Audited.audit_model. This method will be removed.",
Expand Down
18 changes: 9 additions & 9 deletions lib/audited/auditor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def set_audit(options)
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: Audited.audit_class(audited_options[:class_name]).name, inverse_of: :auditable
Audited.audit_class(audited_options[:class_name]).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 @@ -102,7 +102,7 @@ def set_audit(options)
end

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

def update_audited_options(new_options)
Expand Down Expand Up @@ -176,14 +176,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 Audited.audit_class(audited_options[:class_name]).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 Audited.audit_class(audited_options[:class_name]).reconstruct_attributes(audits) unless audits.empty?
end

# List of attributes that are audited.
Expand All @@ -196,8 +196,8 @@ def audited_attributes

# Returns a list combined of record audits and associated audits.
def own_and_associated_audits
Audited.audit_class.unscoped.where(auditable: self)
.or(Audited.audit_class.unscoped.where(associated: self))
Audited.audit_class(audited_options[:class_name]).unscoped.where(auditable: self)
.or(Audited.audit_class(audited_options[:class_name]).unscoped.where(associated: self))
.order(created_at: :desc)
end

Expand Down Expand Up @@ -229,7 +229,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)
Audited.audit_class(audited_options[:class_name]).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 @@ -508,7 +508,7 @@ def enable_auditing
# convenience wrapper around
# @see Audit#as_user.
def audit_as(user, &block)
Audited.audit_class.as_user(user, &block)
Audited.audit_class(audited_options[:class_name]).as_user(user, &block)
end

def auditing_enabled
Expand Down