Skip to content
março 31, 2010 / cassiomarques

Atributos adicionais no acts_as_audited

Em um dos projetos Rails em que estou trabalhando utilizamos o acts_as_audited. Basicamente o que essa gem (ou plugin) faz é gravar, para cada resource que você registrar, quem realizou uma alteração, quando e o que o mudou.

O cliente pediu para adicionarmos um novo atributo nas auditorias. O problema é que o acts_as_audited já possui um conjunto fixo de atributos, inclusive contando com um generator que já gera uma migration pronta para criar a tabela onde as auditorias serão gravadas (audits). Ok, adicionar um novo campo na tabela é fácil, mas e para fazer com que o dado apareça ali? Lá fui eu ler os fontes do acts_as_audited.

No nosso caso específico, precisávamos registrar o id do “dono” do registro alterado, por exemplo, o cliente dono do telefone ou endereço auditado. O acts_as_audited não tem suporte a isso. Eu tinha duas opções:

  • Alterar diretamente o acts_as_audited e ter que manter um fork do projeto com a alteração, lembrando sempre de instalar a gem a partir deste fork quando fosse preparar o ambiente em um novo server ou máquina de desenvolvimento
  • Injetar o novo comportamento sobrescrevendo alguns métodos da gem.

Infelizmente, alterar a gem e submeter um pull request/patch não é uma opção na minha opnião, visto que a alteração é específica demais e não agregaria valor de forma geral a ponto de ser adicionada ao projeto.

Preferi adotar a segunda opção, e no fim foi mais fácil do que eu pensava. Criei um arquivo em lib/ e fiz um require do mesmo em um initializer. A idéia é verificar todos os models que possuem um atributo client_id e para esses mdels alterar os atributos utilizados para criar o registro de auditoria. Como não mexi na gem em si, a não ser que façam mudanças drásticas no código minha alteração deve continuar funcionando sem problemas com atualizações do acts_as_audited.

module CollectiveIdea
  module Acts
    module Audited
      module InstanceMethods
        private
        def audit_create(user = nil)
          write_audit __attributes__('create', user)
        end

        def audit_update(user = nil)
          unless (changes = audited_changes).empty?
            write_audit __attributes__('update', user)
          end
        end

        def audit_destroy(user = nil)
          write_audit __attributes__('destroy', user)
        end        

        def __attributes__(action, user)
          ret = {
            :action  => action,
            :user    => user,
            :changes => action == 'update' ? changes : audited_attributes
          }
          ret.merge!(:client_id => self.client_id) if self.respond_to?(:client_id)
        end
      end
    end
  end
end

Os métodos audit_create, audit_update e audit_destroy são usados internamento pela acts_as_audited como callbacks para criar as auditorias. Usando essa idéia, dá para adicionar qualquer novo atributo.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: