acts_as_diffable

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


License
MIT
Install
gem install acts_as_diffable -v 0.0.1

Documentation

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!