Restoring data using papertrail.

PaperTrail is one of the most used gems to keep track of the events (attributes present in a particular model) happening in the application. But did you know it can be used to restore the data as well? Yes, you read it right. Let’s explore how it can be used to restore the deleted items in the application.

Let’s install the PaperTrail gem first. Let’s add gem "papertrail" to our Gemfile and run bundle install to install the gem. Then we can add a versions table to our database - bundle exec rails generate paper_trail:install The versions table stores data like whodunnit, item_type, item_id, etc. It basically stores all the important information.

Add a new migration for creating a user. rails g migration create_user name email which will create a new user table with the specified fields.

rails db:migrate

Create a new model - rails g model User.

Add has_paper_trail to the model we would like to track the activities for which in this case is the User model. After adding the has_paper_trail line, our user model now looks like this -

class User < ApplicationRecord
  has_paper_trail
end

Let’s create a new user from the rails console. Fire up our rails console using rails console or in short rails c.

User.create(name: 'Sam', email: '[email protected]')

Now, let’s examine the contents of the versions table and analyze how the data is being stored.

PaperTrail::Version.first
#<PaperTrail::Version:0x00000001096aed98 id: 1, item_type: "User", item_id: 1, event: "create", whodunnit: nil, object: nil, created_at: Mon, 03 Apr 2023 15:33:50.856154000 UTC +00:00> # whodunnit is nil because we created post from the console when creating from the real application it stores the ID of the user who created it.

Now let’s delete the post -

Post.first.destroy

The post has been destroyed. Now how do we restore it?

Let’s see what the query PaperTrail::Version yields. Whether it still contains the destroyed post or not.

PaperTrail::Version.first

 => #<PaperTrail::Version:0x000000010bb78e80 id: 1, item_type: "User", item_id: 1, event: "create", whodunnit: nil, object: nil, created_at: Mon, 03 Apr 2023 15:33:50.856154000 UTC +00:00>

What PaperTrail actually does is it saves the pre-changed version of the model, so that it can retrieve and help restore the data back for that model after its data has been deleted. PaperTrail provides a method known as reify to restore the item from that version. Let’s see it in action. But first, let’s query for the post that we deleted based on the item_type and the event which stores the data for the model and the action performed on it -

PaperTrail::Version.where(item_type: "Post", event_type: "create")

=> [#<PaperTrail::Version:0x000000010bb50520
    id: 2,
    item_type: "User",
    item_id: 1,
    event: "destroy",
    whodunnit: nil,
    object:
    "---\nid: 1\nname: New User\nis_valid: t\ncreated_at: !ruby/object:ActiveSupport::TimeWithZone\n  utc: 2023-04-03 15:33:50.856154000 Z\n  zone: &1 !ruby/object:ActiveSupport::TimeZone\n    name: Etc/UTC\n  time: 2023-04-03 15:33:50.856154000 Z\nupdated_at: !ruby/object:ActiveSupport::TimeWithZone\n  utc: 2023-04-03 15:33:50.856154000 Z\n  zone: *1\n  time: 2023-04-03 15:33:50.856154000 Z\n"
PaperTrail::Version.where(item_type: 'User', event: 'destroy').first.reify

This will restore the User model as it was. It only restores the data recorded by the PaperTrail since it’s being used. If we attempt to restore the data before adding the PaperTrail gem, it will fail.

### Summary

PaperTrail’s reify method comes in handy in cases where in production some post was deleted by the user was important and now the person needs it back urgently. You can read more about the reify method from here - PaperTrail.

Need help on your Ruby on Rails or React project?

Join Our Newsletter