Low commit activity in last 3 years
An extension to PaperTrail. Using this gem, you can fetch the ActiveRecord object that was responsible for changes
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

Runtime

>= 11.0.0
 Project Readme

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

  1. Add paper_trail-actor to your Gemfile:
gem "paper_trail-actor"
  1. 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

  1. Please add tests for PRs that are created.
  2. Run the tests bundle exec rake spec to ensure that they all pass.
  3. Lint the code bundle exec rake standard:fix to ensure that convention is maintained.