audited icon indicating copy to clipboard operation
audited copied to clipboard

different audit table per model?

Open francescob opened this issue 6 years ago • 8 comments

is it possibile to have audits saved to different tables, for example <model_name>_audits ? I've managed to save to a different table using the initializer to define a custom audit model, but that apply to all my models. Any idea?

francescob avatar Oct 25 '18 13:10 francescob

I too am interested in this question! Code as it is now looks like this isn't supported, but I'd love to see the option in future.

Marri avatar Jan 23 '19 06:01 Marri

@Marri I think I found a quick and easy solution:

in the initializer I've defined a custom model:

Audited.config do |config|
  config.audit_class = Audit
end

the Audit model is:

class Audit < Audited::Audit self.table_name= 'audits' end

then in the model for which I want to audit to a different table:

before_save :set_audit_table

  def set_audit_table
    ::Audit.table_name = "whateveriwant_audits"
  end

francescob avatar Mar 20 '19 13:03 francescob

@francescob This way is work for me ! Thanks

But I have a little trouble. if executed this callbackbefore_save :set_audit_table then self.table_name will become self.table_name= 'whateveriwant_audits', other modle records will saved to whateveriwant_audits table not audits.

So I have to add:

after_save :init_audit_table
def init_audit_table
    ::Audit.table_name = "audits"
end

But before_save to after_save has a time interval.Maybe other modle records still use whateveriwant_audits table not audits!

Have you ever had this situations?

yanchengv avatar Sep 04 '19 08:09 yanchengv

I provided a clean up method in the Audit class

after_save :clean_up

def clean_up ::Audit.table_name = 'audits' end

do you see any problems with this?

thanks!

timbielawski avatar Oct 24 '19 10:10 timbielawski

I wish that could be configurable too.

oldigor avatar Jan 21 '20 18:01 oldigor

The workarounds above don't seem thread-safe since they are modifying a global Audit.table_name variable. So if you're using multi-threaded gems like Puma or Sidekiq, there will likely be bugs.

jeromedalbert avatar May 08 '20 00:05 jeromedalbert

This appears to be an easy fix from the code. Instead of calling Audited.audit_class, a class method should be defined when you include the module which can then be overridden through the options

e.g. Could instead of calling Audited.audit_class just call audit_class, then allow audit_class_name in the options and define a method https://github.com/collectiveidea/audited/blob/456204de3b16d57a0df4c497615c2cb5509c508b/lib/audited/auditor.rb

def audited(options = {})
  define_method :audit_class do
    options[:audit_class_name]&.safe_constantize || Audit.audit_class
  end
  ...

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

Then when you define your model e.g. User

class User < AR::Base
  audited audit_class_name: 'UserAudit'
end

Associated audits don't even need to use the same class. There may be some other issues to solve around the audited_classes and other helpers. Not really sure what they are used for? I think overall this gem is not super flexible, clearly designed for a specific use case where you only need to audit a single model. I think most of the time you could create this functionality really easily without a gem/dependency tbh.

JoeWoodward avatar Feb 21 '22 07:02 JoeWoodward

Are we accepting feature changes? if yes, I will be happy to raise a PR to address this issue.

kuldeepaggarwal avatar Nov 25 '22 21:11 kuldeepaggarwal