Vous êtes sur la page 1sur 22

Paper Trail Gem:

Track Changes to Your


Models Data

Howdy, today I am going to talk about the


versioning. How to specifically version your models?
So wondering what I am talking about? What is
that versioning and my models?
Let me explain you with an example.
If you have created a specific document that many
people can edit; yes, just similar to Google Docs.
Lets say, its a client proposal and you want your
colleagues to do have a look and if required then
make the validate changes. After sharing the
document with your colleagues, in case someone
does @#$%***&% to your doc or if someone has
updated your doc with the required changes, then
you will not be able to see all the previous versions
of the doc and who changed it. This is the most
common scenario as it creates a big mess.
How To Track changes to your models data
To help you out and track all the changes as well as
who has done this, were going to use Paper Trail
gem. It is a simplified version of Google Docs. A
very, very simplified. This gem lets you track all the
changes, as the purpose of editing and versioning.

And making use of it, you can be able to see all the
previous versions of the file and if required you
can rollback to a previous version of your choice.
You can even undo all the changes after a record
has been destroyed so as to restore it completely.

Why Paper trail?


Its a one stop solution for text data:
It helps to focus on what to look for. Helps to
focus on auditing or versioning.
Relevant data is split across directories, multiple
apps and systems. So instead of source, they can
be managed by username, IP address, message ID.
Setup The App

I am not going to build the application from


scratch. Instead have pulled the code from Github.
Git clone : https://github.com/

Run the migration, bundle and start the app


rake db:migrate
bundle install
rails server
If you head over to localhost:3000, you should see
the following :

PaperTrail
PaperTrail to automatically keep track of what
happened to our documents.
# Gemfile
gem 'paper_trail'
Now, 3 steps in one line to get it to work :
bundle install && bundle exec rails generate
paper_trail:install && bundle exec rake db:migrate
Restart your server before continuing.

After that, add PaperTrail to the model we


want to version :
# app/models/document.rb
class Document < ActiveRecord::Base
belongs_to :user
has_paper_trail
def user_name
user ? user.name : '
end
end
And thats it ! Everytime we save our model, well
get the previous version saved by PaperTrail :
PaperTrail::Version.all
# => #<ActiveRecord::Relation
[#<PaperTrail::Version id: 1, item_type: "Document",
item_id: 1, event: "update", whodunnit: "1", object:
"---\nid: 1\nname: Abcz\ncontent: aaa\nuser_id:
1\ncreat...", created_at: "2014-09-26 15:38:14">]>

Listing the previous versions


# app/helpers/documents_helper.rb
module DocumentsHelper
def
find_version_author_name(version)
user =
User.find_version_author(version)
user ? user.name : ''
end
end

# app/models/user.rb
class User < ActiveRecord::Base
has_many :documents
def
self.find_version_author(version)
find(version.terminator)
end
end
Now, lets add the actual list of versions to
the edit document view as a partial :

Ruby:

And render this partial after the Document


form :
# app/views/documents/edit.html.erb
...
<%= render 'form' %>
<%= render 'documents/versions
,document: @document %>
Now you can udpate any document a few times. You
should see the list of versions growing!

Add Diff & Rollback


First, were going to update the edit document
view to add action to the links :

Then we need the routes :


# config/routes.rb
resources :documents do
resources :versions, only: [:destroy] do
member do
get :diff, to: 'versions#diff
patch :rollback, to: 'versions#rollback
end
end
end

And finally, we create the controller :

You can also rollback to a previous version! Pretty


cool, huh! So for that were going to use the very
nice gem Diffy. Diffy gives us an easy way to diff
content (files or strings) in Ruby by using Unix
diff.

Diff with Diffy


Add the gem to your Gemfile :
# Gemfile
...
gem 'paper_trail
gem 'diffy
...
bundle install and restart your server.

Now the actual diff view is pretty simple to


build. Were going to create it in app/ views/
versions/ :

If you try it, you should see something like


that:.

Very nice! Now, our app is missing one very


important feature. Its a way to bring back
documents from the graveyard!

Custom Version Class


Adding a custom version class is actually quite
easy.
First, we need to generate a migration :
rails g migration create_document_versions
You can paste this in it :

The corresponding model:

Note the default_scope I added.

Bring back Documents

The actions in our controllers:

And a view to list the deleted documents :


# app/views/documents/deleted.html.erb
Bring back documents

Now try it! Delete a document and it will appear


in the list of deleted

MetaData

Remember when we created the migration for you


custom Document Version model ? Were going to
use those!
# app/models/document.rb
...
has_paper_trail class_name: 'DocumentVersion',
meta: { author_username: :user_name,
word_count: :count_word }
When PaperTrail generate a new version, it will
call the defined methods (user_name) on
document an save it in the specified field
(author_username).
We need to add a method named count_word.
def count_word
content.split(' ').count
end
def count_word
content.split(' ').count
end

And since we added all those information, we


should show it in our list of versions.

And save a few versions to see the metadata!

Who needs 100 versions ?


The last trick, We probably dont need the 100
previous versions, 10 to 30 should be enough. You
can define that in PaperTrail configuration :
# config/initializers/paper_trail.rb
PaperTrail.config.version_limit = 10
Source code https://github.com/airblade/paper_trail#1c-basicusage

Features:
1.Stores every update and destroy.
2.Only store updates that has been changed.
3.You can have all the version, including the
original, if it even destroyed once.
4.You can get every version even if the schema
has since changed.
5.Automatically record a responsible controller
current user method.
6.Allows you to set who is responsible at modellevel (useful for migrations).
7.No configuration necessary.
8.Can be turned off/on.
9.Everything can be stored in a single database
table.
10.Thoroughly tested.

Interested in installation

Bacancy Technology has been providing ruby on


rails development services from past 5 years. We
own a strong ROR workforce and have
successfully completed 200+ Rails Application.
Our developers have in-depth knowledge and
skilful expertise in doing all kinds of Ruby on
Rails development work and dealing with any kind
of project.
Numbers of big organizations have made their
way to the top using Rails, and possibly you can
be the next, with the help of Ruby on Rails.