Today I Learned

A Zero One initiative

Browse papertrail changes without object_changes

If you are using PaperTrail to track changes to your data, but are not storing individual changesets, you can still see what changed from version to version using the snippet below:

def hash_diff(from, to)
  from
  .dup
  .delete_if { |k, v| to[k] == v }
  .merge!(to.dup.delete_if { |k, v| from.key?(k) })
end

def present_diff(from_diff, to_diff)
  [].tap do |arr|
    arr << "FROM: #{from_diff}"   if from_diff.present?
    arr << "TO:   #{to_diff}\n\n" if to_diff.present?
  end
end

def list_papertrail_changes_for(obj)
  obj.versions.each_with_index.flat_map do |ver, idx|
    next if ver.object.nil?

    this_ver     = YAML.load(ver.object)
    next_version = obj.versions[idx + 1] || ver
    next_ver     = YAML.load(next_version.object)

    from_diff = hash_diff(this_ver, next_ver)
    to_diff   = hash_diff(next_ver, this_ver)

    present_diff(from_diff, to_diff)
  end.compact
end

puts list_papertrail_changes_for(thing)

FROM: {"ip_address"=>"", "updated_at"=>"2021-04-06T07:32:26.432Z"}
TO:   {"ip_address"=>"10.27.57.194", "updated_at"=>"2021-04-06T08:14:03.506Z"}

FROM: {"ip_address"=>"10.27.57.194", "updated_at"=>"2021-04-06T08:14:03.506Z"}
TO:   {"ip_address"=>"", "updated_at"=>"2021-04-09T13:47:07.485Z"}
Looking for help? Each developer at Zero One has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.