PaperTrail-Actor
This gem is an extension for PaperTrail that allows you to set an ActiveRecord
object as the "whodunnit" field. This enhancement provides more granular tracking of who made changes, making it easier to trace modifications in your application.
Features
-
Set an ActiveRecord Object for Whodunnit: Use an
ActiveRecord
object to track who made changes. -
Return the ActiveRecord Object: The method
#actor
can be used to get the object responsible for changes. - Coexistence with Existing Versions: Works seamlessly alongside existing PaperTrail versions, regardless of when they were created.
How it works
This gem works by storing the globalid to the whodunnit field of PaperTrail version tables. This allows you to add different object types to the whodunnit field, know exactly which object is responsible, and retrive that object with ease.
For example, if you have both Admin
objects and User
objects that are capable of making changes, this gem ensures that you can clearly identify who made the change instead of using purely an ID and not knowing if it was for an Admin
or a User
Installation
- Add
paper_trail-actor
to your Gemfile:
gem "paper_trail-actor"
- Run the following command:
bundle install
Usage
Basic Setup
To use this gem, you first need to set a user (or any ActiveRecord
object) to the whodunnit
field.
product = Product.find(42)
admin = Admin.find(1)
PaperTrail.request.whodunnit = admin
PaperTrail.request.whodunnit # "gid://app/Admin/1"
PaperTrail.request.actor # Returns the `Admin` object with id 1
When you update the product, PaperTrail will remember who made the change:
product.update(name: "Ice cream")
product.versions.last.whodunnit # "gid://app/Admin/1"
product.versions.last.actor # Returns the `Admin` object with id 1
Flexible Whodunnit
The gem is designed to be flexible. You can set whodunnit
with various types of objects:
-
Strings:
PaperTrail.request.whodunnit = "Alex the admin" # "Alex the admin"
-
New/unpersisted ActiveRecord Objects:
PaperTrail.request.whodunnit = Admin.new # Sets the string representation of the admin
-
Non-ActiveRecord Objects:
class Job def to_s "A job in the system" end end PaperTrail.request.whodunnit = Job.new # "A job in the system"
When you update the product, PaperTrail will store the string for who made the change:
product.update(name: "Ice cream")
product.versions.last.whodunnit # "A job in the system"
product.versions.last.actor # "A job in the system"
Updating Existing Versions
If you have existing PaperTrail versions and need to update them, you can do so by:
first_product_version = product.versions.first
admin_id = first_product_version.actor # For example, "1"
admin = Admin.find_by(id: admin_id)
if admin.present?
first_product_version.whodunnit = admin
first_product_version.save
end
Setting whodunnit with a controller callback
You can set the user for PaperTrail in the same way that the PaperTrail documentation states.
However, setting this to an ActiveRecord object now records the globalid. It also allows the object to be retrived from created PaperTrail versions with the #actor
method.
If your controller has a #current_user
method, PaperTrail-Actor will assign the globalid of the current user to whodunnit. If your controller doesn't have a #current_user
, or if the current user is nil
, then whodunnit will not be set.
You may want set #user_for_paper_trail
to call a different method to find out who is responsible. To do so, override the #user_for_paper_trail
method in your controller:
class ApplicationController < ActionController::Base
before_action :set_paper_trail_whodunnit
def user_for_paper_trail
logged_in? ? current_admin : "Public user"
end
end
Contributing
- Please add tests for PRs that are created.
- Run the tests
bundle exec rake spec
to ensure that they all pass. - Lint the code
bundle exec rake standard:fix
to ensure that convention is maintained.