= DeepDive Deep Contolled Cloning
{}[https://gitter.im/flajann2/deep_dive?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
When you have a system of objects that have many references to each other, it becomes an
issue to be able to clone properly that object graph. There may be control objects you may
not want to clone, but maintain references to. And some references you may not wish to clone at all.
Enter DeepDive. Allows you a means by which you can do controlled deep cloning or
copying of your complex interconnected objects.
== Gem Version
{}[http://badge.fury.io/rb/deep_dive]
== Usage
Simply include DeepDive in your base class. All classes derived will be set
for deep cloning or deep duping.
=== Debugging
In some cases, you may need to get a dump of classes DeepDive is replicating,
particulary if you need to hunt down objects whose instance variables might
need to be added to the exclsion list. In that case, you may turn on the verbose
mode, thusly:
DeepDive.verbose = true
in which case you will get a dump to stdout of all the classes
of the objects it copies, which can be copious depending on your
application.
== Examples
class FooBase
include DeepDive
exclude :c
end
Even though the instance variable @c is not defined in the base class, any instance
variables with that name in the subclasses will be excluded from the deep clone or duping.
It will simply use the reference to that object instead (a.k.a shallow copying)
class Foo < FooBase
attr_accessor :a, :b, :c, :changeme
end
class Bar < FooBase
attr_accessor :a, :b, :c, :changeme
end
class FooBar < FooBase
attr_accessor :a, :b, :c, :changeme, :dontcopy, :arr, :hsh, :nonddob
exclude :dontcopy
end
class FooBlock < FooBar
attr_accessor :freject, :fa, :fb, :fc, :frecur, :fexcludeme
exclude { |sym, obj|
sym == :@fexcludeme if obj.instance_variable_defined?(:@freject) and obj.send(:freject)
}
end
@foo = Foo.new
@bar = Bar.new
@foobar = FooBar.new
@foobar.arr = [@foo, @bar, @foobar, "Just a string"]
@foobar.hsh = {foo: @foo, bar: @bar, foobar: @foobar, nonddob: "just a string"}
@foo.a = 'foo just around'
@bar.a = 'bar hanging around'
@foo.b = @bar
@bar.b = @foo
@foo.c = @bar.c = @foobar.c = @foobar
@foo.changeme = @bar.changeme = @foobar.changeme = "initial"
So now if you do:
nfoo = @foo.dclone
@foo.c will refer to the same object as nfoo.c,
but @foo.b and nfoo.b will be different, as nfoo.b will be a deep clone of @foo.b.
Also, you may do:
mfoo = @foo.ddup
which will basically do a deep dup of @foo.
Please see spec/lib/deep_dive/deep_dive_spec.rb for a more comprehensve example
of the above. Better documentation will be supplied shortly.
=== Patching
In some rare circumstances, you may need to patch an instance
variable in your object graph during deep copying. Like for
instance, when a child object is being cloned seprately from a different
parent to be associated with a new parent.
We introduce patching. The instance variable
@foo.parent = @oldparent
pf = @foo.dclone parent: @newparent
pf.parent.should == @newparent
And all variables named "parent" in the object graph will
pick up the new reference.
== Note Well
DeepDive is expected to undergo rapid evolution until it hits 1.0.0. I will take
every effort to keep the API backwards compatable until then.
== Release Notes
2015-07-07 0.3.0 -- Added debugging and deep patching based on
instance variable names.
2014-07-27 0.2.0 -- Implemented the exclusion block,
made gem restrictive to Ruby 2.x and higher.
== Copyright
Copyright (c) 2013-2014 Fred Mitchell. See LICENSE.txt for
further details.