Model Auditing on Rails

When a system interacts with different users and have access to create, modify and/or eliminate data sometimes it's necessary to control who performed the action on the record of a table, which was the data modified and deleted, and the date of that action.

In rails applications, if we create a table from the migration generators only a basic audit is included by default, which are the attributes created_at and updated_at. This information on each record of a table is insufficient to answer, for example, the following questions:

Which user modify the records?
Which records was modify?
Who deleted some records and when was it?

In order to answer these and other questions, we must give a more solid support to the implementation of our tables.

There are numerous implementations to solve this problem, for example, to save the events to audit in a text file, to launch triggers from the database, to save the events in the same database, etc.

What I am going to present on this occasion is a gem that uses a table in the database to keep events and information modified by users responding to the questions asked above

Instalation and config

1) As always we need to add to the gemfile to Gemfile

gem 'paper_trail'  

2) Add a versions table to your database and an initializer file for configuration:

bundle exec rails generate paper_trail:install  
bundle exec rake db:migrate  

3) Add haspapertrail to the models you want to track.

class Product < ActiveRecord::Base  
  has_paper_trail
end  

4) If your controllers have a current_user method, you can easily track who is responsible for changes by adding a controller callback.

class ApplicationController  
  before_action :set_paper_trail_whodunnit
end  

Once we have done these simple steps, the Product model will be audited automatically when we perform 'update', 'create', or 'destroy' actions. To check it we can go to a rails console and type the following:

product = Product.create(name: “product 1”, description: “description 1”)  

This will create the first version of product 1 in the version table and we can verify it as follows:

p = product.versions.last  
p.event                     # ‘create’     possible events -> 'update', 'create', or 'destroy'  
p.created_at             # When the `event` occurred  
p.whodunnit             # If the update was via a controller and the  

If we continue and update the name of the product, then we re-consult and we would obtain the following:

product.update_attributes :name => 'product A'  
product.versions.last.name             # 'product A'  
product.versions.last.event             # 'update'  

PaperTrail saves a full version of the previous state of the records, allowing you to view the state of an object at any point in its life cycle, revert to a particular version or even restore a deleted record.

Conclusión

Using one of these gems is very easy to perform an audit of the tables of our application, giving to the administrators the feeling of peace. I consider it to be a powerful tool for auditing and even recover deleted information in the database.

Please leave a comment if you want or you can contact us or take a tour in our brochure.