2
I am developing a logging process on my system (Rails 5), more specifically within the application controller. This process is being created there so I can add one before_save us controllers that I want to record logs. As are several controllers, I am centralizing the method instead of repeating it several times in each file.
The logging process works like this: when the user clicks on the "Save" button on form editing, the system fetches in the BD the current record of the object the user is editing and compare these records with the fields of the form. If the records are different, it means that the user has changed some data. The old data is saved as log and the new data is saved to the BD. 
Follow down what I’ve got so far:
def gerar_log
    @controlr = instance_variable_get("@#{controller_name.singularize}") #objeto que está sendo editado
    nome_cols = @controlr.attribute_names #pega o nome das colunas da tabela do objeto
    ctrl_obj = @controlr.attributes #pega os dados do objeto do BD
    dados_editados = self.strong_params #pega os strong params do controller, que contém o que foi alterado nos campos do form. Estou preso aqui =/
    ...
    ##compara os dados_editados com os dados atuais do objeto e verifica se algo mudou
end
The problem I’m having in this process is time to catch the strong parameters of controller. How is a method private, can’t call him directly. I tried to create a method public, called strong_params, that returns the params of the private method, but it generates the following error: param is missing or the value is empty:. If anyone knows of a solution to this or if there is some better and equally dynamic way to do this process that is not within the application controller, I am grateful if you can inform me.
EDIT - I do not intend to use gems for this process, because it is something super simple. The only obstacle at the moment is to dynamically obtain the strong parameters of each controller. If I can’t do it inside application_controller, I can do by defining a method within each controller as follows:
../controllers/persons_controller.erb
def log
    @pessoas = Pessoa.find(params[:id]) #busca a pessoa que está sendo editada
    colunas = @pessoas.attribute_names #pega o nome das colunas da tabela pessoa
    parametros = pessoa_params.merge(:id => params[:id]) #pega os dados que estão sendo editados no form e adiciona o ID
    pess = @pessoas.attributes #pega os dados da pessoa do BD
    alteracoes = {}
    colunas.each_index do |i|
    ##compara os dados_editados com os dados atuais do objeto e verifica se algo mudou
    #Se mudou, atualiza a pessoa com os novos dados e salva os dados antigos na tabela de log
      if parametros[colunas[i]].to_s != pess[colunas[i]].to_s 
        alteracoes[colunas[i]] = pess[colunas[i]].to_s unless parametros[colunas[i]].nil?
      end
    end
    @logs = Log.new
    @logs.gera_log(current_user.id, controller_name, params[:id], alteracoes) unless alteracoes.nil? || alteracoes.empty?
  end
To generate log before the user updates the information:
before_save :log, only: [:update]
The bright side of this is that it does exactly what I need. The bad side is that I need to define this method in each controller that I want to generate log, and that goes against policy DRY (Don't Repeat Yourself). So I want to know if there’s a way to centralize this method and make it dynamic for each controller, without using gems!
You don’t do that in the controller, but in the model. There’s a Gem that does what you need, https://github.com/collectiveidea/audited
– Alex Takitani