No commit activity in last 3 years
No release in over 3 years
ActsAsDiffable provides a dead-simple way to compare two instances of a class, including any or all associations, or more complex relationships.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 2.3.14
 Project Readme

ActsAsDiffable provides a dead-simple way to compare two instances of a class, including any or all associations, or more complex relationships.

The return is a hash*, suitable for digestion by case-based textualizers, JSON processors, etc., in the form { 'attribute' => [from, to] }

(* In the instance of no changes, a nil is returned)

Usage

class Foo < ActiveRecord::Base acts_as_diffable end

Foo.first.diff(Foo.last) => { 'bar' => ['foo', nil] }

Associations

For plural associations, a :diff_key option needs to be added to the association, defining how to relate disparate instances within each parent's collections.
This can be a single field or a collection of fields in an array, and will be expressed as the key side of a hash with the value being the hash of attribute differences.

For singular association, there is no need to specify a way to organize and compare, so we only need to express which associations to include in the diff, by adding a :diff option to the association that evaluates to true.

class Foo < ActiveRecord::Base acts_as_diffable

has_one :bar, :diff => true
has_many :fish, :diff_keypattern => :name
has_and_belongs_to_many :users, :diff_keypattern => [:firstname, :lastname]

end

Foo.first.diff(Foo.last) => { 'bar' => { 'attr1' => ['a', 'b'], 'attr2' => [14, nil] }, 'fish => { 'nemo' => {'fish_attr1' => [nil, 'zip'] }, 'goldie' => {'fish_attr1' => ['zap', 'zop'] } }, 'users' => { ['Jane', 'Doe'] => { 'firstname' => 'Jane', 'lastname' => 'Doe' }, ['John', 'Doe'] => { '_deleted' => true } } }

More complex relationships

In addition to the marked associations, any method on the class that returns an ActiveRecord-ish object can be included in the diff by adding a manual_diff_definiton. For comparing collections of ActiveRecord objects, use the form:

manual_diff_definition :name, :eval => 'instance_eval_code', :diff_key => [:key, :pattern]

For simpler singular comparisons, omit the diff_key option.

Have a lot of fun!