collectiveidea / audited

Audited (formerly acts_as_audited) is an ORM extension that logs all changes to your Rails models.
MIT License
3.38k stars 661 forks source link

different audit table per model? #471

Open francescob opened 5 years ago

francescob commented 5 years ago

is it possibile to have audits saved to different tables, for example _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?

Marri commented 5 years ago

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.

francescob commented 5 years ago

@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
yanchengv commented 5 years ago

@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_namewill 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?

timbielawski commented 4 years ago

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!

oldigor commented 4 years ago

I wish that could be configurable too.

jeromedalbert commented 4 years ago

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.

JoeWoodward commented 2 years ago

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.

kuldeepaggarwal commented 1 year ago

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