full_clone 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWI0NTg2ZTJkZTk0NTRmYzFiNTY1OGI1MGY2ODM3YjMyODRmNTFmNg==
5
+ data.tar.gz: !binary |-
6
+ MmExOWRiMTNkMGY0ZmUzMDYzOTk3NTgxOTQ5MzNkZmVhYjhhNmI0ZA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NTc0MGJlNWYyYmZkZWZmMjRiMDFkMTMyYjVjNjk4YTAxOTdhNzQ2Y2M2ZWE3
10
+ Zjc2MmQyYjhhMDExYWVjYzkyOWNiZTk4Y2FkZTRhY2NhZjRmMTM4OGI5ZThj
11
+ YjYyOGM3YTRlNDQ3YmYxMmQyZDIyNWE0ZGViOWVkNWM3MzcwNDM=
12
+ data.tar.gz: !binary |-
13
+ ODQ2NTdhN2FlNGIzMDk5MzczNzkzNjU4NDFjOTA1OTcyZTVmNDY5NmI3OWM3
14
+ ODk4OTIxOTIzYTlhZTRjMWZkNGVhMjAwNTFiZWY4YWQyZDM1MDQ5ZmE4YzY3
15
+ M2Y5YjIyZWJmYTc1ZGRiMDg3NmYzZTMzZWUwNDc4OTFiYjhhOGY=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in deep_clone.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Peter Camilleri
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # DeepClone
2
+
3
+ The standard clone method creates a fresh instance of most (non-scalar) objects
4
+ but does not clone internal state. This internal state remains aliased in the
5
+ cloned copy. The full_clone method digs deep and makes copies of these internal
6
+ variables. It also allows classes to specify an exclusion list of variable that
7
+ are not to be processed.
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'full_clone'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install full_clone
20
+
21
+ ## Usage
22
+
23
+ require 'full_clone'
24
+
25
+ then, in those places where regular clone was problematic, use:
26
+
27
+ foo = my_object.full_clone
28
+
29
+ instead of
30
+
31
+ foo = my_object.clone
32
+
33
+ To exclude some instance variables from the deep cloning process, define a
34
+ full_clone_exclude method in the required class:
35
+
36
+ def full_clone_exclude
37
+ [:@bad_var1, :@bad_var2, :@bad_var_etc]
38
+ end
39
+
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rake/testtask'
2
+ require "bundler/gem_tasks"
3
+
4
+ #Run the unit test suite.
5
+ Rake::TestTask.new do |t|
6
+ #List out all the test files.
7
+ t.test_files = ["test/deep_clone_tests.rb",
8
+ "test/object_tests.rb",
9
+ "test/array_tests.rb",
10
+ "test/hash_tests.rb",
11
+ "test/struct_tests.rb"]
12
+ t.verbose = false
13
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'full_clone/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "full_clone"
8
+ spec.version = DeepClone::VERSION
9
+ spec.authors = ["Peter Camilleri"]
10
+ spec.email = ["peter.c.camilleri@gmail.com"]
11
+ spec.description = "A (safe/no exceptions) clone variant that performs a deep, recursive copy."
12
+ spec.summary = "A clone variant that performs a deep copy."
13
+ spec.homepage = "http://teuthida-technologies.com/"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ # spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'minitest'
24
+
25
+ end
@@ -0,0 +1,21 @@
1
+ class Array
2
+
3
+ #The full_clone method for arrays.
4
+ def full_clone(progress={})
5
+ progress[object_id] = result = clone
6
+ exclude = full_clone_exclude
7
+
8
+ each_index.each do |name|
9
+
10
+ unless exclude.include?(name)
11
+ value = result[name]
12
+ value = progress[value.object_id] || value.full_clone(progress)
13
+ result[name] = value
14
+ end
15
+
16
+ end
17
+
18
+ result
19
+ end
20
+
21
+ end
@@ -0,0 +1,21 @@
1
+ class Hash
2
+
3
+ #The full_clone method for structs.
4
+ def full_clone(progress={})
5
+ progress[object_id] = result = clone
6
+ exclude = full_clone_exclude
7
+
8
+ each_key do |name|
9
+
10
+ unless exclude.include?(name)
11
+ value = result[name]
12
+ value = progress[value.object_id] || value.full_clone(progress)
13
+ result[name] = value
14
+ end
15
+
16
+ end
17
+
18
+ result
19
+ end
20
+
21
+ end
@@ -0,0 +1,26 @@
1
+ class Object
2
+
3
+ #By default, no instance variables are excluded.
4
+ def full_clone_exclude
5
+ []
6
+ end
7
+
8
+ #The full_clone method for most objects.
9
+ def full_clone(progress={})
10
+ progress[object_id] = result = clone
11
+ exclude = full_clone_exclude
12
+
13
+ instance_variables.each do |name|
14
+
15
+ unless exclude.include?(name)
16
+ value = result.instance_variable_get(name)
17
+ value = progress[value.object_id] || value.full_clone(progress)
18
+ result.instance_variable_set(name, value)
19
+ end
20
+
21
+ end
22
+
23
+ result
24
+ end
25
+
26
+ end
@@ -0,0 +1,21 @@
1
+ class Struct
2
+
3
+ #The full_clone method for structs.
4
+ def full_clone(progress={})
5
+ progress[object_id] = result = clone
6
+ exclude = full_clone_exclude
7
+
8
+ members.each do |name|
9
+
10
+ unless exclude.include?(name)
11
+ value = result[name]
12
+ value = progress[value.object_id] || value.full_clone(progress)
13
+ result[name] = value
14
+ end
15
+
16
+ end
17
+
18
+ result
19
+ end
20
+
21
+ end
@@ -0,0 +1,3 @@
1
+ module DeepClone
2
+ VERSION = "0.0.1"
3
+ end
data/lib/full_clone.rb ADDED
@@ -0,0 +1,35 @@
1
+ require_relative 'full_clone/version'
2
+ require_relative 'full_clone/object'
3
+ require_relative 'full_clone/array'
4
+ require_relative 'full_clone/hash'
5
+ require_relative 'full_clone/struct'
6
+
7
+ module DeepClone
8
+ def full_clone(_progress={})
9
+ self
10
+ end
11
+ end
12
+
13
+ class Numeric
14
+ include DeepClone
15
+ end
16
+
17
+ class NilClass
18
+ include DeepClone
19
+ end
20
+
21
+ class TrueClass
22
+ include DeepClone
23
+ end
24
+
25
+ class FalseClass
26
+ include DeepClone
27
+ end
28
+
29
+ class Symbol
30
+ include DeepClone
31
+ end
32
+
33
+ class Regexp
34
+ include DeepClone
35
+ end
@@ -0,0 +1,83 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/full_clone'
4
+ require 'minitest/autorun'
5
+
6
+ #Test the monkey patches applied to the Object class.
7
+ class ArrayDeepCloneTester < MiniTest::Unit::TestCase
8
+
9
+ #Special initialize to track rake progress.
10
+ def initialize(*all)
11
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
12
+
13
+ if $do_this_only_one_time != __FILE__
14
+ puts
15
+ puts "Running test file: #{File.split(__FILE__)[1]}"
16
+ $do_this_only_one_time = __FILE__
17
+ end
18
+
19
+ super(*all)
20
+ end
21
+
22
+ def test_basic_deep_cloning
23
+ sa = "North"
24
+ simple1 = [sa, 5, nil]
25
+ simple2 = simple1.full_clone
26
+
27
+ assert_equal(simple1[0], simple2[0])
28
+ assert_equal(simple1[1], 5)
29
+ assert_equal(simple1[2], nil)
30
+ refute_equal(simple1[0].object_id, simple2[0].object_id)
31
+
32
+ sa << "West"
33
+
34
+ assert_equal(sa, "NorthWest")
35
+ assert_equal(simple1[0], "NorthWest")
36
+ assert_equal(simple2[0], "North")
37
+ end
38
+
39
+ def test_with_exclusion
40
+ sa = "North"
41
+ simple1 = [sa, 5, nil]
42
+ simple1.define_singleton_method(:full_clone_exclude) {[0]}
43
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
44
+ simple2 = simple1.full_clone
45
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
46
+
47
+ assert_equal(simple1[0], simple2[0])
48
+ assert_equal(simple1[1], 5)
49
+ assert_equal(simple1[2], nil)
50
+ assert_equal(simple1[0].object_id, simple2[0].object_id)
51
+ end
52
+
53
+ def test_with_direct_looping
54
+ simple1 = ['East', 5, nil]
55
+ simple1[2] = simple1
56
+ simple2 = simple1.full_clone
57
+
58
+ assert_equal(simple2.object_id, simple2[2].object_id)
59
+ refute_equal(simple1.object_id, simple2[2].object_id)
60
+ end
61
+
62
+ def test_with_direct_looping_and_exclusion
63
+ simple1 = ['East', 5, nil]
64
+ simple1.define_singleton_method(:full_clone_exclude) {[2]}
65
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
66
+ simple1[2] = simple1
67
+ simple2 = simple1.full_clone
68
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
69
+
70
+ refute_equal(simple2.object_id, simple2[2].object_id)
71
+ assert_equal(simple1.object_id, simple2[2].object_id)
72
+ end
73
+
74
+ def test_with_indirect_looping
75
+ simple1 = ['East', 5, nil]
76
+ simple3 = ['West', 6, simple1]
77
+ simple1[2] = simple3
78
+ simple2 = simple1.full_clone
79
+
80
+ assert_equal(simple2.object_id, simple2[2][2].object_id)
81
+ end
82
+
83
+ end
@@ -0,0 +1,43 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/full_clone'
4
+ require 'minitest/autorun'
5
+
6
+ #Test the monkey patches applied to the Object class.
7
+ class DeepCloneTester < MiniTest::Unit::TestCase
8
+
9
+ #Special initialize to track rake progress.
10
+ def initialize(*all)
11
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
12
+
13
+ if $do_this_only_one_time != __FILE__
14
+ puts
15
+ puts "Running test file: #{File.split(__FILE__)[1]}"
16
+ $do_this_only_one_time = __FILE__
17
+ end
18
+
19
+ super(*all)
20
+ end
21
+
22
+ def test_for_safe_value_cloning
23
+ assert_equal((6).full_clone, 6)
24
+ assert_equal((6).full_clone.object_id, (6).object_id)
25
+
26
+ assert_equal((:foo).full_clone, :foo)
27
+ assert_equal((:foo).full_clone.object_id, (:foo).object_id)
28
+
29
+ assert_equal((true).full_clone, true)
30
+ assert_equal((true).full_clone.object_id, (true).object_id)
31
+
32
+ assert_equal((false).full_clone, false)
33
+ assert_equal((false).full_clone.object_id, (false).object_id)
34
+
35
+ assert_equal((nil).full_clone, nil)
36
+ assert_equal((nil).full_clone.object_id, (nil).object_id)
37
+
38
+ rex = /ABC/
39
+ assert_equal(rex.full_clone, rex)
40
+ assert_equal(rex.full_clone.object_id, rex.object_id)
41
+ end
42
+
43
+ end
@@ -0,0 +1,83 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/full_clone'
4
+ require 'minitest/autorun'
5
+
6
+ #Test the monkey patches applied to the Object class.
7
+ class HashDeepCloneTester < MiniTest::Unit::TestCase
8
+
9
+ #Special initialize to track rake progress.
10
+ def initialize(*all)
11
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
12
+
13
+ if $do_this_only_one_time != __FILE__
14
+ puts
15
+ puts "Running test file: #{File.split(__FILE__)[1]}"
16
+ $do_this_only_one_time = __FILE__
17
+ end
18
+
19
+ super(*all)
20
+ end
21
+
22
+ def test_basic_deep_cloning
23
+ sa = "North"
24
+ simple1 = {iva: sa, ivb: 5, ivc: nil}
25
+ simple2 = simple1.full_clone
26
+
27
+ assert_equal(simple1[:iva], simple2[:iva])
28
+ assert_equal(simple1[:ivb], 5)
29
+ assert_equal(simple1[:ivc], nil)
30
+ refute_equal(simple1[:iva].object_id, simple2[:iva].object_id)
31
+
32
+ sa << "West"
33
+
34
+ assert_equal(sa, "NorthWest")
35
+ assert_equal(simple1[:iva], "NorthWest")
36
+ assert_equal(simple2[:iva], "North")
37
+ end
38
+
39
+ def test_with_exclusion
40
+ sa = "North"
41
+ simple1 = {iva: sa, ivb: 5, ivc: nil}
42
+ simple1.define_singleton_method(:full_clone_exclude) {[:iva]}
43
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
44
+ simple2 = simple1.full_clone
45
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
46
+
47
+ assert_equal(simple1[:iva], simple2[:iva])
48
+ assert_equal(simple1[:ivb], 5)
49
+ assert_equal(simple1[:ivc], nil)
50
+ assert_equal(simple1[:iva].object_id, simple2[:iva].object_id)
51
+ end
52
+
53
+ def test_with_direct_looping
54
+ simple1 = {iva: 'East', ivb: 5, ivc: nil}
55
+ simple1[:ivc] = simple1
56
+ simple2 = simple1.full_clone
57
+
58
+ assert_equal(simple2.object_id, simple2[:ivc].object_id)
59
+ refute_equal(simple1.object_id, simple2[:ivc].object_id)
60
+ end
61
+
62
+ def test_with_direct_looping_and_exclusion
63
+ simple1 = {iva: 'East', ivb: 5, ivc: nil}
64
+ simple1.define_singleton_method(:full_clone_exclude) {[:ivc]}
65
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
66
+ simple1[:ivc] = simple1
67
+ simple2 = simple1.full_clone
68
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
69
+
70
+ refute_equal(simple2.object_id, simple2[:ivc].object_id)
71
+ assert_equal(simple1.object_id, simple2[:ivc].object_id)
72
+ end
73
+
74
+ def test_with_indirect_looping
75
+ simple1 = {iva: 'East', ivb: 5, ivc: nil}
76
+ simple3 = {iva: 'West', ivb: 6, ivc: simple1}
77
+ simple1[:ivc] = simple3
78
+ simple2 = simple1.full_clone
79
+
80
+ assert_equal(simple2.object_id, simple2[:ivc][:ivc].object_id)
81
+ end
82
+
83
+ end
@@ -0,0 +1,93 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/full_clone'
4
+ require 'minitest/autorun'
5
+
6
+ #Test the monkey patches applied to the Object class.
7
+ class ObjectDeepCloneTester < MiniTest::Unit::TestCase
8
+
9
+ class SimpleClass
10
+ attr_accessor :iva
11
+ attr_accessor :ivb
12
+ attr_accessor :ivc
13
+
14
+ def initialize(iva, ivb, ivc)
15
+ @iva, @ivb, @ivc = iva, ivb, ivc
16
+ end
17
+ end
18
+
19
+ #Special initialize to track rake progress.
20
+ def initialize(*all)
21
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
22
+
23
+ if $do_this_only_one_time != __FILE__
24
+ puts
25
+ puts "Running test file: #{File.split(__FILE__)[1]}"
26
+ $do_this_only_one_time = __FILE__
27
+ end
28
+
29
+ super(*all)
30
+ end
31
+
32
+ def test_basic_deep_cloning
33
+ sa = "North"
34
+ simple1 = SimpleClass.new(sa, 5, nil)
35
+ simple2 = simple1.full_clone
36
+
37
+ assert_equal(simple1.iva, simple2.iva)
38
+ assert_equal(simple1.ivb, 5)
39
+ assert_equal(simple1.ivc, nil)
40
+ refute_equal(simple1.iva.object_id, simple2.iva.object_id)
41
+
42
+ sa << "West"
43
+
44
+ assert_equal(sa, "NorthWest")
45
+ assert_equal(simple1.iva, "NorthWest")
46
+ assert_equal(simple2.iva, "North")
47
+ end
48
+
49
+ def test_with_exclusion
50
+ sa = "North"
51
+ simple1 = SimpleClass.new(sa, 5, nil)
52
+ simple1.define_singleton_method(:full_clone_exclude) {[:@iva]}
53
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
54
+ simple2 = simple1.full_clone
55
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
56
+
57
+ assert_equal(simple1.iva, simple2.iva)
58
+ assert_equal(simple1.ivb, 5)
59
+ assert_equal(simple1.ivc, nil)
60
+ assert_equal(simple1.iva.object_id, simple2.iva.object_id)
61
+ end
62
+
63
+ def test_with_direct_looping
64
+ simple1 = SimpleClass.new('East', 5, nil)
65
+ simple1.ivc = simple1
66
+ simple2 = simple1.full_clone
67
+
68
+ assert_equal(simple2.object_id, simple2.ivc.object_id)
69
+ refute_equal(simple1.object_id, simple2.ivc.object_id)
70
+ end
71
+
72
+ def test_with_direct_looping_and_exclusion
73
+ simple1 = SimpleClass.new('East', 5, nil)
74
+ simple1.define_singleton_method(:full_clone_exclude) {[:@ivc]}
75
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
76
+ simple1.ivc = simple1
77
+ simple2 = simple1.full_clone
78
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
79
+
80
+ refute_equal(simple2.object_id, simple2.ivc.object_id)
81
+ assert_equal(simple1.object_id, simple2.ivc.object_id)
82
+ end
83
+
84
+ def test_with_indirect_looping
85
+ simple1 = SimpleClass.new('East', 5, nil)
86
+ simple3 = SimpleClass.new('West', 6, simple1)
87
+ simple1.ivc = simple3
88
+ simple2 = simple1.full_clone
89
+
90
+ assert_equal(simple2.object_id, simple2.ivc.ivc.object_id)
91
+ end
92
+
93
+ end
@@ -0,0 +1,85 @@
1
+ # coding: utf-8
2
+
3
+ require_relative '../lib/full_clone'
4
+ require 'minitest/autorun'
5
+
6
+ #Test the monkey patches applied to the Object class.
7
+ class StructDeepCloneTester < MiniTest::Unit::TestCase
8
+
9
+ SimpleStruct = Struct.new(:iva, :ivb, :ivc)
10
+
11
+ #Special initialize to track rake progress.
12
+ def initialize(*all)
13
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
14
+
15
+ if $do_this_only_one_time != __FILE__
16
+ puts
17
+ puts "Running test file: #{File.split(__FILE__)[1]}"
18
+ $do_this_only_one_time = __FILE__
19
+ end
20
+
21
+ super(*all)
22
+ end
23
+
24
+ def test_basic_deep_cloning
25
+ sa = "North"
26
+ simple1 = SimpleStruct.new(sa, 5, nil)
27
+ simple2 = simple1.full_clone
28
+
29
+ assert_equal(simple1.iva, simple2.iva)
30
+ assert_equal(simple1.ivb, 5)
31
+ assert_equal(simple1.ivc, nil)
32
+ refute_equal(simple1.iva.object_id, simple2.iva.object_id)
33
+
34
+ sa << "West"
35
+
36
+ assert_equal(sa, "NorthWest")
37
+ assert_equal(simple1.iva, "NorthWest")
38
+ assert_equal(simple2.iva, "North")
39
+ end
40
+
41
+ def test_with_exclusion
42
+ sa = "North"
43
+ simple1 = SimpleStruct.new(sa, 5, nil)
44
+ simple1.define_singleton_method(:full_clone_exclude) {[:iva]}
45
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
46
+ simple2 = simple1.full_clone
47
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
48
+
49
+ assert_equal(simple1.iva, simple2.iva)
50
+ assert_equal(simple1.ivb, 5)
51
+ assert_equal(simple1.ivc, nil)
52
+ assert_equal(simple1.iva.object_id, simple2.iva.object_id)
53
+ end
54
+
55
+ def test_with_direct_looping
56
+ simple1 = SimpleStruct.new('East', 5, nil)
57
+ simple1.ivc = simple1
58
+ simple2 = simple1.full_clone
59
+
60
+ assert_equal(simple2.object_id, simple2.ivc.object_id)
61
+ refute_equal(simple1.object_id, simple2.ivc.object_id)
62
+ end
63
+
64
+ def test_with_direct_looping_and_exclusion
65
+ simple1 = SimpleStruct.new('East', 5, nil)
66
+ simple1.define_singleton_method(:full_clone_exclude) {[:ivc]}
67
+ assert_equal(simple1.singleton_methods, [:full_clone_exclude])
68
+ simple1.ivc = simple1
69
+ simple2 = simple1.full_clone
70
+ assert_equal(simple2.singleton_methods, [:full_clone_exclude])
71
+
72
+ refute_equal(simple2.object_id, simple2.ivc.object_id)
73
+ assert_equal(simple1.object_id, simple2.ivc.object_id)
74
+ end
75
+
76
+ def test_with_indirect_looping
77
+ simple1 = SimpleStruct.new('East', 5, nil)
78
+ simple3 = SimpleStruct.new('West', 6, simple1)
79
+ simple1.ivc = simple3
80
+ simple2 = simple1.full_clone
81
+
82
+ assert_equal(simple2.object_id, simple2.ivc.ivc.object_id)
83
+ end
84
+
85
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: full_clone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Peter Camilleri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A (safe/no exceptions) clone variant that performs a deep, recursive
56
+ copy.
57
+ email:
58
+ - peter.c.camilleri@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - deep_clone.gemspec
69
+ - lib/full_clone.rb
70
+ - lib/full_clone/array.rb
71
+ - lib/full_clone/hash.rb
72
+ - lib/full_clone/object.rb
73
+ - lib/full_clone/struct.rb
74
+ - lib/full_clone/version.rb
75
+ - test/array_tests.rb
76
+ - test/deep_clone_tests.rb
77
+ - test/hash_tests.rb
78
+ - test/object_tests.rb
79
+ - test/struct_tests.rb
80
+ homepage: http://teuthida-technologies.com/
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.1.4
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: A clone variant that performs a deep copy.
104
+ test_files:
105
+ - test/array_tests.rb
106
+ - test/deep_clone_tests.rb
107
+ - test/hash_tests.rb
108
+ - test/object_tests.rb
109
+ - test/struct_tests.rb
110
+ has_rdoc: