# Gemfile
gem 'paper_trail'
# Terminal
rails g papertrail:install
rails db:migrate
# config/initializers/paper_trail.rb
PaperTrail.config.track_associations = false
PaperTrail.config.version_limit = 3
PaperTrail.serializer = PaperTrail::Serializers::JSON
PaperTrail::Version.class_eval do
def changed_object
@changed_object ||= JSON.parse(self.object, object_class: OpenStruct)
end
end
# user.rb
class User < ApplicationRecord
has_paper_trail on: [:update, :destroy], only: [:first_name, :last_name]
end
# show.html.erb
<h2>Versions</h2>
<table class='table'>
<thead>
<tr>
<th>ID</th>
<th>Modifier</th>
<th>Action</th>
<th>Changes</th>
</tr>
</thead>
<tbody>
<% @user.versions.each do |version| %>
<%= tag.tr do %>
<%= tag.td version.id %>
<%= tag.td version.whodunnit %>
<%= tag.td link_to 'rollback', user_rollback_path(@user, version: version) %>
<%= tag.td do %>
<%= tag.ul class: 'list-group' do %>
<li class='list-group-item'>
<strong>First Name:</strong>
<%= version.changed_object.first_name %>
</li>
<li class='list-group-item'>
<strong>Last Name:</strong>
<%= version.changed_object.last_name %>
</li>
<li class='list-group-item'>
<strong>Email:</strong>
<%= version.changed_object.email %>
</li>
<% end %>
<% end %>
<% end %>
<% end %>
</table>
# application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :set_paper_trail_whodunnit
def user_for_paper_trail
# user_signed_in? ? current_user.id : 'Public user'
'Public user'
end
end
# routes.rb
Rails.application.routes.draw do
resources :users do
get :rollback
end
root to: 'users#index'
end
# users_controller.rb
def rollback
@user = User.find(params[:user_id])
version = @user.versions.find(params[:version])
if version.reify.save
redirect_to @user, notice: 'User was successfully rollbacked.'
else
render :show
end
end