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