Sunday, 4 December 2016

Track changes to your Rails models with PaperTrail


Sometime, it's become necessary to keep the record of how a model looked at any stage in its lifecycle and may be we want to revert it to previous version, or restore it after it has been destroyed.

For this situation PaperTrail comes with great solution. PaperTrail stores the pre-change version of the model, unlike some other auditing/versioning plugins, so you can retrieve the original version. This is useful when you start keeping a paper trail for models that already have records in the database.

So, in Gemfile: -

gem 'paper_trail'

Run command below to generate and migrate paper_trail which will 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

Add the following line to your model (app/models/post.rb):

class Post < ActiveRecord::Base
  has_paper_trail
end


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

You can specified it on action

class Post < ActiveRecord::Base
  has_paper_trail on: [:update, :create]
end


You can also specify which changes should not be tracked.

In model:-

has_paper_trail ignore: [:column_name]

Some fields can be skipped, they will neither be tracked nor included in the serialized version of the object.

has_paper_trail skip: [:column_name]

Now, you can display the audited versions, It’s easy, just, add the following route-

get '/posts/history', to: 'posts#history', as: :posts_history

Add a history method to the controller (app/controllers/posts_controller.rb):-

def history
  @versions = PaperTrail::Version.order('created_at DESC')
end

Rendering the view history (app/views/posts/history.html.erb):-

<div class="container">
  <h1>History</h1>

  <ul>
    <% @versions.each do |version| %>
      <li>
        <%= l(version.created_at, format: "%-d.%m.%Y %H:%M:%S %Z") %><br/>
        Event ID: <%= version.id %><br/>
        <b>Target:</b> <%= version.item_type %>
        <small>(id: <%= version.item_id %>)</small>; <b>action</b> <%= version.event %>;<br/>
        <div>
          More info:
          <pre><%= version.object %></pre>
        </div>
      </li>
    <% end %>
  </ul>
</div>

No comments:

Post a Comment