-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Auditing via paper_trail (change history)
paper_trail is a gem used for auditing and versioning your models. We can easily use it with active_admin to show a list of recently modified items in the admin screen.
Example:
-
Install PaperTrail as a gem via your
Gemfile
:gem 'paper_trail'
-
Generate a migration which will add a
versions
table to your database:rails generate paper_trail:install
-
Run the migration:
rake db:migrate
-
Add
user_for_paper_trail
to controller so paper_trail knows which user updated the item and thebefore_action :set_paper_trail_whodunnit
(see https://git.io/vrTsk why you need to do this). (optional)
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_paper_trail_whodunnit
# ...
protected
def user_for_paper_trail
admin_user_signed_in? ? current_admin_user.try(:id) : 'Unknown user'
end
# ...
end
- Add
has_paper_trail
to the models you want to track:
# app/models/post.rb
class Post < ActiveRecord::Base
has_paper_trail
# ...
end
- Display the versions table on the dashboard
# app/admin/dashboard.rb
section "Recently updated content" do
table_for PaperTrail::Version.order('id desc').limit(20) do # Use PaperTrail::Version if this throws an error
column ("Item") { |v| v.item }
# column ("Item") { |v| link_to v.item, [:admin, v.item] } # Uncomment to display as link
column ("Type") { |v| v.item_type.underscore.humanize }
column ("Modified at") { |v| v.created_at.to_s :long }
column ("Admin") { |v| link_to AdminUser.find(v.whodunnit).email, [:admin, AdminUser.find(v.whodunnit)] }
end
end
To link the item
column to your model in active_admin use:
column ("Item") do |v|
if v.item
link_to v.item, [:admin, v.item]
end
end
in app/admin/posts.rb
:
controller do
def show
@post = Post.includes(versions: :item).find(params[:id])
@versions = @post.versions
@post = @post.versions[params[:version].to_i].reify if params[:version]
show! #it seems to need this
end
end
sidebar :versionate, :partial => "layouts/version", :only => :show
then create the partial in app/views/layouts/_version.html.erb
with this:
<% if !@versions.empty? %>
<h3>Current Version: <%= @versions.length %></h3>
<b>Created At:</b>
<%= @versions.last.created_at%>
<br>
<b>Admin</b>: <%= AdminUser.find(@versions.last.whodunnit).email %>
<br>
<% if @versions.length.to_i > 1 %>
<% if params[:version].to_i > 1 || !params[:version] %>
<%= link_to "Previous version", {:version => (params[:version] || @versions.length).to_i - 1}%>
<br>
<% end %>
<% if params[:version] %>
<h3>This is <%= "#{params[:version]}"%> version</h3>
<b>Modify at:</b>
<%= @versions[(params[:version].to_i - 1)].created_at %>
<br>
<b>Admin</b>:
<%= AdminUser.find(@versions[(params[:version].to_i - 1)].whodunnit).email %>
<br>
<%= link_to "Go to current version"%>
<% end %>
<% end %>
<% else %>
<p>This item does not have any registered version.</p>
<% end %>
###Adding a history page.
you can add it by including a member action. like this
in
admin/posts.rb
add
...
member_action :history do
@post = Post.find(params[:id])
@versions = @post.versions
render "layouts/history"
end
...
Then create the file
app/views/layouts/history.html.arb
with
panel "Historia" do
table_for assigns[:versions]
end
Visit /admin/post/:id/history
to see history for a particular post.