PaperTrail HashDiff Adapter

Adapter for the popular versioning/auditing tool PaperTrail This gem allows you to store only incremental changes in the object_changes column. This is especially useful when you are storing hashes in a json/b column and would like to track changes for each key. Uses HashDiff

Usage

Add the gem 'paper_trail-hashdiff' to your Gemfile.

In your paper_trail.rb initializer, add the following:

require 'paper_trail_hashdiff'
PaperTrail.config.object_changes_adapter = PaperTrailHashDiff.new

Additionally, if you want to limit storing these changes for only object columns (eg. json hashes or arrays) and skip primitives, you can use the "only_objects" option when initializing:

PaperTrail.config.object_changes_adapter = PaperTrailHashDiff.new(only_objects: true)

Note: With this option, the where_object_changes method from PT may not work properly.

Storage format

say you have a jsonb column called 'custom_values' as follows:

{
  name: 'abc'
  age: 5,
  tags: ['a', 'b']
}

and it is changed to

{
  name: 'def'
  age: 5,
  tags: ['a', 'c']
}

Previously the object_changes column would have been stored as follows:

{
  custom_values: [
    {
      name: 'abc',
      age: 5,
      tags: ['a', 'b']
    },
    {
      name: 'def',
      age: 5,
      tags: ['a', 'c']
    }
  ]
}

With this change, it will be stored as follows:

{
  custom_values: [
    ["~", [:name], "abc", "def"], ["-", [:tags, 1], "b"], ["+", [:tags, 1], "c"]
  ]
}

As you can see, the keys that were not changed (i.e. in this case, age) will not appear in the object changes at all, thus increasing storage efficiency.