deep_cloneable 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/Gemfile +3 -2
- data/README.rdoc +21 -17
- data/VERSION +1 -1
- data/deep_cloneable.gemspec +8 -4
- data/lib/deep_cloneable.rb +11 -5
- data/test/test_deep_cloneable.rb +191 -170
- metadata +26 -12
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
ODQ0NDJiMzkwMzY5YzNlYmMyNjc1NTlmZTIxOWNiMDcyNjg1NWJiOGYyMGJh
|
10
|
-
N2I4NDY3YWNiZmRhNjkyNTExMDMwYzBlNWZhMTEyODk0ZmM0ZGNkZDMzZmQw
|
11
|
-
MDIzYjI3OTdlYmEyOWMzNWRmZTQzZjU3NTU0NDc2MjI0NTk4NGE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YzhkMmVkYWQxYjk1MDhhMTU0MTlmNjNjNGI4NTZiNTc2M2FiZWVjOGVkNTZh
|
14
|
-
NDI3NGU0YjUzMjFkNzZlNWRjMmY0ODhlZmI0MzBjZjM0M2YzNjczZjQzZWY0
|
15
|
-
ZGVjNGU0OGEzYWQ1MDYxM2E1Njc5ZDU4Y2NlYzA2OTY2OWFjY2I=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4f8ee9b4a7a7e7e22b8a9b329e4cf95c7d5bed93
|
4
|
+
data.tar.gz: d6b6a654ee08c7c0fd903d9a75e30043033785be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 161420b3d29dd21abd32e702f78eefed39b3dc70bad588dc94841f01c47c5e68ad71843b5d02dc70f7b5d6b893c3ee9f337cb3431e60657b4ab3919fd74d31f7
|
7
|
+
data.tar.gz: aa4d87c683367f05c1be6bc5cbf2ea725a9ec3a5a8ce5352c0f548bcb9fe7ff24303cbe07b92b41ca8eb64d2972b873748b4b99d1e77f2a96863b1096a13b89c
|
data/Gemfile
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
|
-
gem 'minitest', :group => :test
|
4
3
|
gem 'activerecord', '>= 3.1.0'
|
5
|
-
gem 'activesupport', '>= 3.1.0'
|
4
|
+
gem 'activesupport', '>= 3.1.0'
|
5
|
+
|
6
|
+
gem 'minitest', :group => :test
|
6
7
|
gem 'appraisal', :group => :test
|
7
8
|
gem 'sqlite3', :group => :test
|
8
9
|
gem 'rdoc', '>= 2.4.2', :group => :test
|
data/README.rdoc
CHANGED
@@ -16,62 +16,66 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
|
|
16
16
|
|
17
17
|
* In your Gemfile:
|
18
18
|
|
19
|
-
gem 'deep_cloneable', '~> 1.
|
19
|
+
gem 'deep_cloneable', '~> 1.7.0'
|
20
|
+
|
21
|
+
== Note
|
22
|
+
|
23
|
+
Version 1.7.0 deprecates the use of the method 'dup' for deep cloning. Please update your code to use 'deep_clone' instead. The dup method will be removed in deep_cloneable 2.0.0.
|
20
24
|
|
21
25
|
== Example
|
22
26
|
|
23
27
|
=== Cloning one single association
|
24
|
-
pirate.
|
28
|
+
pirate.deep_clone :include => :mateys
|
25
29
|
|
26
30
|
=== Cloning multiple associations
|
27
|
-
pirate.
|
31
|
+
pirate.deep_clone :include => [:mateys, :treasures]
|
28
32
|
|
29
33
|
=== Cloning really deep
|
30
|
-
pirate.
|
34
|
+
pirate.deep_clone :include => {:treasures => :gold_pieces}
|
31
35
|
|
32
36
|
=== Cloning really deep with multiple associations
|
33
|
-
pirate.
|
37
|
+
pirate.deep_clone :include => [:mateys, {:treasures => :gold_pieces}]
|
34
38
|
|
35
39
|
=== Cloning really deep with multiple associations and a dictionary
|
36
40
|
|
37
41
|
A dictionary ensures that models are not cloned multiple times when it is associated to nested models.
|
38
42
|
When using a dictionary, ensure recurring associations are cloned first:
|
39
43
|
|
40
|
-
pirate.
|
44
|
+
pirate.deep_clone :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :use_dictionary => true
|
41
45
|
|
42
46
|
If this is not an option for you, it is also possible to populate the dictionary manually in advance:
|
43
47
|
|
44
48
|
dict = { :mateys => {} }
|
45
|
-
pirate.mateys.each{|m| dict[:mateys][m] = m.
|
46
|
-
pirate.
|
49
|
+
pirate.mateys.each{|m| dict[:mateys][m] = m.deep_clone }
|
50
|
+
pirate.deep_clone :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :dictionary => dict
|
47
51
|
|
48
|
-
When an object isn't found in the dictionary, it will be populated. By passing in an empty dictionary you can populate it automatically and reuse it in subsequent
|
52
|
+
When an object isn't found in the dictionary, it will be populated. By passing in an empty dictionary you can populate it automatically and reuse it in subsequent deep_clones to avoid creating multiples of the same object where you have overlapping associations.
|
49
53
|
|
50
54
|
=== Cloning a model without an attribute
|
51
|
-
pirate.
|
55
|
+
pirate.deep_clone :except => :name
|
52
56
|
|
53
57
|
=== Cloning a model without multiple attributes
|
54
|
-
pirate.
|
58
|
+
pirate.deep_clone :except => [:name, :nick_name]
|
55
59
|
|
56
60
|
=== Cloning a model without an attribute or nested multiple attributes
|
57
|
-
pirate.
|
61
|
+
pirate.deep_clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
|
58
62
|
|
59
63
|
=== Cloning with a block
|
60
|
-
pirate.
|
64
|
+
pirate.deep_clone :include => :parrot do |original, kopy|
|
61
65
|
kopy.cloned_from_id = original.id if kopy.respond_to?(:cloned_from_id)
|
62
66
|
end
|
63
67
|
|
64
68
|
=== Cloning without validations
|
65
|
-
pirate.
|
69
|
+
pirate.deep_clone :include => {:treasures => :gold_pieces}, :validate => false
|
66
70
|
|
67
71
|
=== Cloning a model with only explicitly assigned attribute
|
68
|
-
pirate.
|
72
|
+
pirate.deep_clone :only => :name
|
69
73
|
|
70
74
|
=== Cloning a model with only multiple explicitly assigned attributes
|
71
|
-
pirate.
|
75
|
+
pirate.deep_clone :only => [:name, :nick_name]
|
72
76
|
|
73
77
|
=== Cloning a model with explicitly assigned attributes or nested multiple attributes
|
74
|
-
pirate.
|
78
|
+
pirate.deep_clone :include => :parrot, :only => [:name, { :parrot => [:name] }]
|
75
79
|
|
76
80
|
== Note on Patches/Pull Requests
|
77
81
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.7.0
|
data/deep_cloneable.gemspec
CHANGED
@@ -2,14 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: deep_cloneable 1.7.0 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
8
|
s.name = "deep_cloneable"
|
8
|
-
s.version = "1.
|
9
|
+
s.version = "1.7.0"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
11
13
|
s.authors = ["Reinier de Lange"]
|
12
|
-
s.date = "2014-
|
14
|
+
s.date = "2014-06-25"
|
13
15
|
s.description = "Extends the functionality of ActiveRecord::Base#clone to perform a deep clone that includes user specified associations. "
|
14
16
|
s.email = "r.j.delange@nedforce.nl"
|
15
17
|
s.extra_rdoc_files = [
|
@@ -44,8 +46,7 @@ Gem::Specification.new do |s|
|
|
44
46
|
"test/test_helper.rb"
|
45
47
|
]
|
46
48
|
s.homepage = "http://github.com/moiristo/deep_cloneable"
|
47
|
-
s.
|
48
|
-
s.rubygems_version = "2.0.6"
|
49
|
+
s.rubygems_version = "2.2.2"
|
49
50
|
s.summary = "This gem gives every ActiveRecord::Base object the possibility to do a deep clone."
|
50
51
|
|
51
52
|
if s.respond_to? :specification_version then
|
@@ -53,11 +54,14 @@ Gem::Specification.new do |s|
|
|
53
54
|
|
54
55
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
56
|
s.add_runtime_dependency(%q<activerecord>, [">= 3.1.0"])
|
57
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.1.0"])
|
56
58
|
else
|
57
59
|
s.add_dependency(%q<activerecord>, [">= 3.1.0"])
|
60
|
+
s.add_dependency(%q<activesupport>, [">= 3.1.0"])
|
58
61
|
end
|
59
62
|
else
|
60
63
|
s.add_dependency(%q<activerecord>, [">= 3.1.0"])
|
64
|
+
s.add_dependency(%q<activesupport>, [">= 3.1.0"])
|
61
65
|
end
|
62
66
|
end
|
63
67
|
|
data/lib/deep_cloneable.rb
CHANGED
@@ -17,18 +17,18 @@ class ActiveRecord::Base
|
|
17
17
|
end
|
18
18
|
|
19
19
|
# Deep dups an ActiveRecord model. See README.rdoc
|
20
|
-
def
|
20
|
+
def deep_clone *args, &block
|
21
21
|
options = args[0] || {}
|
22
22
|
|
23
23
|
dict = options[:dictionary]
|
24
24
|
dict ||= {} if options.delete(:use_dictionary)
|
25
25
|
|
26
26
|
kopy = unless dict
|
27
|
-
|
27
|
+
dup()
|
28
28
|
else
|
29
29
|
tableized_class = self.class.name.tableize.to_sym
|
30
30
|
dict[tableized_class] ||= {}
|
31
|
-
dict[tableized_class][self] ||=
|
31
|
+
dict[tableized_class][self] ||= dup()
|
32
32
|
end
|
33
33
|
|
34
34
|
block.call(self, kopy) if block
|
@@ -91,10 +91,16 @@ class ActiveRecord::Base
|
|
91
91
|
return kopy
|
92
92
|
end
|
93
93
|
|
94
|
+
def dup *args, &block
|
95
|
+
return super() if args.empty? && !block
|
96
|
+
ActiveSupport::Deprecation.warn("Calling dup with arguments or blocks is deprecated and will be removed in deep_cloneable 2. Use method 'deep_clone' instead.")
|
97
|
+
deep_clone *args, &block
|
98
|
+
end
|
99
|
+
|
94
100
|
private
|
95
101
|
|
96
102
|
def dup_belongs_to_association options, &block
|
97
|
-
self.send(options[:association]) && self.send(options[:association]).
|
103
|
+
self.send(options[:association]) && self.send(options[:association]).deep_clone(options[:dup_options], &block)
|
98
104
|
end
|
99
105
|
|
100
106
|
def dup_has_one_association options, &block
|
@@ -109,7 +115,7 @@ class ActiveRecord::Base
|
|
109
115
|
end.try(:name)
|
110
116
|
|
111
117
|
self.send(options[:association]).collect do |obj|
|
112
|
-
tmp = obj.
|
118
|
+
tmp = obj.deep_clone(options[:dup_options], &block)
|
113
119
|
tmp.send("#{primary_key_name}=", nil)
|
114
120
|
tmp.send("#{reverse_association_name.to_s}=", options[:copy]) if reverse_association_name
|
115
121
|
tmp
|
data/test/test_deep_cloneable.rb
CHANGED
@@ -11,155 +11,155 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
11
11
|
@ship = BattleShip.create(:name => 'Black Pearl', :pirates => [@jack])
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
16
|
-
assert
|
17
|
-
assert
|
18
|
-
assert_equal @jack.name, @jack.
|
19
|
-
assert_nil
|
20
|
-
assert_equal @jack.nick_name,
|
21
|
-
end
|
22
|
-
|
23
|
-
def
|
24
|
-
|
25
|
-
assert
|
26
|
-
assert
|
27
|
-
assert_nil
|
28
|
-
assert_equal 'no nickname',
|
29
|
-
assert_equal @jack.age,
|
30
|
-
end
|
31
|
-
|
32
|
-
def
|
33
|
-
|
34
|
-
assert
|
35
|
-
assert
|
36
|
-
assert_equal @jack.name,
|
37
|
-
assert_equal 'no nickname',
|
38
|
-
assert_nil
|
39
|
-
assert_nil
|
40
|
-
assert_nil
|
41
|
-
end
|
42
|
-
|
43
|
-
def
|
44
|
-
|
45
|
-
assert
|
46
|
-
assert
|
47
|
-
assert_equal @jack.name,
|
48
|
-
assert_equal @jack.nick_name,
|
49
|
-
assert_nil
|
50
|
-
assert_nil
|
51
|
-
assert_nil
|
14
|
+
def test_single_deep_clone_exception
|
15
|
+
deep_clone = @jack.deep_clone(:except => :name)
|
16
|
+
assert deep_clone.new_record?
|
17
|
+
assert deep_clone.save
|
18
|
+
assert_equal @jack.name, @jack.deep_clone.name
|
19
|
+
assert_nil deep_clone.name
|
20
|
+
assert_equal @jack.nick_name, deep_clone.nick_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_multiple_deep_clone_exception
|
24
|
+
deep_clone = @jack.deep_clone(:except => [:name, :nick_name])
|
25
|
+
assert deep_clone.new_record?
|
26
|
+
assert deep_clone.save
|
27
|
+
assert_nil deep_clone.name
|
28
|
+
assert_equal 'no nickname', deep_clone.nick_name
|
29
|
+
assert_equal @jack.age, deep_clone.age
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_single_deep_clone_onliness
|
33
|
+
deep_clone = @jack.deep_clone(:only => :name)
|
34
|
+
assert deep_clone.new_record?
|
35
|
+
assert deep_clone.save
|
36
|
+
assert_equal @jack.name, deep_clone.name
|
37
|
+
assert_equal 'no nickname', deep_clone.nick_name
|
38
|
+
assert_nil deep_clone.age
|
39
|
+
assert_nil deep_clone.ship_id
|
40
|
+
assert_nil deep_clone.ship_type
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_multiple_deep_clone_onliness
|
44
|
+
deep_clone = @jack.deep_clone(:only => [:name, :nick_name])
|
45
|
+
assert deep_clone.new_record?
|
46
|
+
assert deep_clone.save
|
47
|
+
assert_equal @jack.name, deep_clone.name
|
48
|
+
assert_equal @jack.nick_name, deep_clone.nick_name
|
49
|
+
assert_nil deep_clone.age
|
50
|
+
assert_nil deep_clone.ship_id
|
51
|
+
assert_nil deep_clone.ship_type
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_single_include_association
|
55
|
-
|
56
|
-
assert
|
57
|
-
assert
|
58
|
-
assert_equal 1,
|
55
|
+
deep_clone = @jack.deep_clone(:include => :mateys)
|
56
|
+
assert deep_clone.new_record?
|
57
|
+
assert deep_clone.save
|
58
|
+
assert_equal 1, deep_clone.mateys.size
|
59
59
|
end
|
60
60
|
|
61
61
|
def test_single_include_belongs_to_polymorphic_association
|
62
|
-
|
63
|
-
assert
|
64
|
-
assert
|
65
|
-
refute_nil
|
66
|
-
refute_equal @jack.ship,
|
62
|
+
deep_clone = @jack.deep_clone(:include => :ship)
|
63
|
+
assert deep_clone.new_record?
|
64
|
+
assert deep_clone.save
|
65
|
+
refute_nil deep_clone.ship
|
66
|
+
refute_equal @jack.ship, deep_clone.ship
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_single_include_has_many_polymorphic_association
|
70
|
-
|
71
|
-
assert
|
72
|
-
assert
|
73
|
-
assert
|
70
|
+
deep_clone = @ship.deep_clone(:include => :pirates)
|
71
|
+
assert deep_clone.new_record?
|
72
|
+
assert deep_clone.save
|
73
|
+
assert deep_clone.pirates.any?
|
74
74
|
end
|
75
75
|
|
76
76
|
def test_multiple_include_association
|
77
|
-
|
78
|
-
assert
|
79
|
-
assert
|
80
|
-
assert_equal 1,
|
81
|
-
assert_equal 1,
|
77
|
+
deep_clone = @jack.deep_clone(:include => [:mateys, :treasures])
|
78
|
+
assert deep_clone.new_record?
|
79
|
+
assert deep_clone.save
|
80
|
+
assert_equal 1, deep_clone.mateys.size
|
81
|
+
assert_equal 1, deep_clone.treasures.size
|
82
82
|
end
|
83
83
|
|
84
84
|
def test_deep_include_association
|
85
|
-
|
86
|
-
assert
|
87
|
-
assert
|
88
|
-
assert_equal 1,
|
89
|
-
assert_equal 1,
|
85
|
+
deep_clone = @jack.deep_clone(:include => {:treasures => :gold_pieces})
|
86
|
+
assert deep_clone.new_record?
|
87
|
+
assert deep_clone.save
|
88
|
+
assert_equal 1, deep_clone.treasures.size
|
89
|
+
assert_equal 1, deep_clone.gold_pieces.size
|
90
90
|
end
|
91
91
|
|
92
92
|
def test_include_association_assignments
|
93
|
-
|
94
|
-
assert
|
93
|
+
deep_clone = @jack.deep_clone(:include => :treasures)
|
94
|
+
assert deep_clone.new_record?
|
95
95
|
|
96
|
-
|
97
|
-
assert_equal
|
96
|
+
deep_clone.treasures.each do |treasure|
|
97
|
+
assert_equal deep_clone, treasure.pirate
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
def test_multiple_and_deep_include_association
|
102
|
-
|
103
|
-
assert
|
104
|
-
assert
|
105
|
-
assert_equal 1,
|
106
|
-
assert_equal 1,
|
107
|
-
assert_equal 1,
|
102
|
+
deep_clone = @jack.deep_clone(:include => {:treasures => :gold_pieces, :mateys => {}})
|
103
|
+
assert deep_clone.new_record?
|
104
|
+
assert deep_clone.save
|
105
|
+
assert_equal 1, deep_clone.treasures.size
|
106
|
+
assert_equal 1, deep_clone.gold_pieces.size
|
107
|
+
assert_equal 1, deep_clone.mateys.size
|
108
108
|
end
|
109
109
|
|
110
110
|
def test_multiple_and_deep_include_association_with_array
|
111
|
-
|
112
|
-
assert
|
113
|
-
assert
|
114
|
-
assert_equal 1,
|
115
|
-
assert_equal 1,
|
116
|
-
assert_equal 1,
|
111
|
+
deep_clone = @jack.deep_clone(:include => [{:treasures => :gold_pieces}, :mateys])
|
112
|
+
assert deep_clone.new_record?
|
113
|
+
assert deep_clone.save
|
114
|
+
assert_equal 1, deep_clone.treasures.size
|
115
|
+
assert_equal 1, deep_clone.gold_pieces.size
|
116
|
+
assert_equal 1, deep_clone.mateys.size
|
117
117
|
end
|
118
118
|
|
119
119
|
def test_with_belongs_to_relation
|
120
|
-
|
121
|
-
assert
|
122
|
-
assert
|
123
|
-
refute_equal
|
120
|
+
deep_clone = @jack.deep_clone(:include => :parrot)
|
121
|
+
assert deep_clone.new_record?
|
122
|
+
assert deep_clone.save
|
123
|
+
refute_equal deep_clone.parrot, @jack.parrot
|
124
124
|
end
|
125
125
|
|
126
126
|
def test_should_pass_nested_exceptions
|
127
|
-
|
128
|
-
assert
|
129
|
-
assert
|
130
|
-
refute_equal
|
131
|
-
assert_equal
|
127
|
+
deep_clone = @jack.deep_clone(:include => :parrot, :except => [:name, { :parrot => [:name] }])
|
128
|
+
assert deep_clone.new_record?
|
129
|
+
assert deep_clone.save
|
130
|
+
refute_equal deep_clone.parrot, @jack.parrot
|
131
|
+
assert_equal deep_clone.parrot.age, @jack.parrot.age
|
132
132
|
refute_nil @jack.parrot.name
|
133
|
-
assert_nil
|
133
|
+
assert_nil deep_clone.parrot.name
|
134
134
|
end
|
135
135
|
|
136
136
|
def test_should_pass_nested_onlinesses
|
137
|
-
|
138
|
-
assert
|
139
|
-
assert
|
140
|
-
refute_equal
|
141
|
-
assert_equal
|
142
|
-
assert_nil
|
137
|
+
deep_clone = @jack.deep_clone(:include => :parrot, :only => [:name, { :parrot => [:name] }])
|
138
|
+
assert deep_clone.new_record?
|
139
|
+
assert deep_clone.save
|
140
|
+
refute_equal deep_clone.parrot, @jack.parrot
|
141
|
+
assert_equal deep_clone.parrot.name, @jack.parrot.name
|
142
|
+
assert_nil deep_clone.parrot.age
|
143
143
|
end
|
144
144
|
|
145
|
-
def
|
145
|
+
def test_should_not_double_deep_clone_when_using_dictionary
|
146
146
|
current_matey_count = Matey.count
|
147
|
-
|
148
|
-
assert
|
149
|
-
|
147
|
+
deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
|
148
|
+
assert deep_clone.new_record?
|
149
|
+
deep_clone.save!
|
150
150
|
|
151
151
|
assert_equal current_matey_count + 1, Matey.count
|
152
152
|
end
|
153
153
|
|
154
|
-
def
|
154
|
+
def test_should_not_double_deep_clone_when_using_manual_dictionary
|
155
155
|
current_matey_count = Matey.count
|
156
156
|
|
157
157
|
dict = { :mateys => {} }
|
158
|
-
@jack.mateys.each{|m| dict[:mateys][m] = m.
|
158
|
+
@jack.mateys.each{|m| dict[:mateys][m] = m.deep_clone }
|
159
159
|
|
160
|
-
|
161
|
-
assert
|
162
|
-
|
160
|
+
deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
|
161
|
+
assert deep_clone.new_record?
|
162
|
+
deep_clone.save!
|
163
163
|
|
164
164
|
assert_equal current_matey_count + 1, Matey.count
|
165
165
|
end
|
@@ -168,21 +168,21 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
168
168
|
@human = Animal::Human.create :name => "Michael"
|
169
169
|
@pig = Animal::Pig.create :human => @human, :name => 'big pig'
|
170
170
|
|
171
|
-
|
172
|
-
assert
|
173
|
-
assert
|
174
|
-
assert_equal 1,
|
171
|
+
deep_clone_human = @human.deep_clone(:include => [:pigs])
|
172
|
+
assert deep_clone_human.new_record?
|
173
|
+
assert deep_clone_human.save
|
174
|
+
assert_equal 1, deep_clone_human.pigs.count
|
175
175
|
|
176
176
|
@human2 = Animal::Human.create :name => "John"
|
177
177
|
@pig2 = @human2.pigs.create :name => 'small pig'
|
178
178
|
|
179
|
-
|
180
|
-
assert
|
181
|
-
assert
|
182
|
-
assert_equal 1,
|
179
|
+
deep_clone_human_2 = @human.deep_clone(:include => [:pigs])
|
180
|
+
assert deep_clone_human_2.new_record?
|
181
|
+
assert deep_clone_human_2.save
|
182
|
+
assert_equal 1, deep_clone_human_2.pigs.count
|
183
183
|
end
|
184
184
|
|
185
|
-
def
|
185
|
+
def test_should_deep_clone_many_to_many_associations
|
186
186
|
@human = Animal::Human.create :name => "Michael"
|
187
187
|
@human2 = Animal::Human.create :name => "Jack"
|
188
188
|
@chicken1 = Animal::Chicken.create :name => 'Chick1'
|
@@ -190,24 +190,24 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
190
190
|
@human.chickens << [@chicken1, @chicken2]
|
191
191
|
@human2.chickens << [@chicken1, @chicken2]
|
192
192
|
|
193
|
-
|
194
|
-
assert
|
195
|
-
assert
|
196
|
-
assert_equal 2,
|
193
|
+
deep_clone_human = @human.deep_clone(:include => :ownerships)
|
194
|
+
assert deep_clone_human.new_record?
|
195
|
+
assert deep_clone_human.save
|
196
|
+
assert_equal 2, deep_clone_human.chickens.count
|
197
197
|
end
|
198
198
|
|
199
|
-
def
|
200
|
-
|
199
|
+
def test_should_deep_clone_with_block
|
200
|
+
deep_clone = @jack.deep_clone(:include => :parrot) do |original, kopy|
|
201
201
|
kopy.cloned_from_id = original.id
|
202
202
|
end
|
203
203
|
|
204
|
-
assert
|
205
|
-
assert
|
206
|
-
assert_equal @jack.id,
|
207
|
-
assert_equal @jack.parrot.id,
|
204
|
+
assert deep_clone.new_record?
|
205
|
+
assert deep_clone.save
|
206
|
+
assert_equal @jack.id, deep_clone.cloned_from_id
|
207
|
+
assert_equal @jack.parrot.id, deep_clone.parrot.cloned_from_id
|
208
208
|
end
|
209
209
|
|
210
|
-
def
|
210
|
+
def test_should_deep_clone_habtm_associations
|
211
211
|
@person1 = Person.create :name => "Bill"
|
212
212
|
@person2 = Person.create :name => "Ted"
|
213
213
|
@car1 = Car.create :name => 'Mustang'
|
@@ -215,42 +215,42 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
215
215
|
@person1.cars << [@car1, @car2]
|
216
216
|
@person2.cars << [@car1, @car2]
|
217
217
|
|
218
|
-
|
218
|
+
deep_clone_person = @person1.deep_clone :include => :cars
|
219
219
|
|
220
|
-
assert
|
221
|
-
assert_equal [@person1, @person2,
|
222
|
-
assert_equal [@person1, @person2,
|
220
|
+
assert deep_clone_person.new_record?
|
221
|
+
assert_equal [@person1, @person2, deep_clone_person], @car1.people
|
222
|
+
assert_equal [@person1, @person2, deep_clone_person], @car2.people
|
223
223
|
|
224
|
-
assert
|
224
|
+
assert deep_clone_person.save
|
225
225
|
|
226
|
-
# did NOT
|
226
|
+
# did NOT deep_clone the Car instances
|
227
227
|
assert_equal 2, Car.all.count
|
228
228
|
|
229
|
-
# did
|
230
|
-
assert_equal @person1.cars,
|
231
|
-
assert_equal 2,
|
229
|
+
# did deep_clone the correct join table rows
|
230
|
+
assert_equal @person1.cars, deep_clone_person.cars
|
231
|
+
assert_equal 2, deep_clone_person.cars.count
|
232
232
|
end
|
233
233
|
|
234
|
-
def
|
234
|
+
def test_should_deep_clone_habtm_associations_with_missing_reverse_association
|
235
235
|
@coin = Coin.create :value => 1
|
236
236
|
@person = Person.create :name => "Bill"
|
237
237
|
@coin.people << @person
|
238
238
|
|
239
|
-
|
240
|
-
assert
|
239
|
+
deep_clone = @coin.deep_clone :include => :people
|
240
|
+
assert deep_clone.new_record?
|
241
241
|
assert_equal [@person], @coin.people
|
242
|
-
assert
|
242
|
+
assert deep_clone.save
|
243
243
|
end
|
244
244
|
|
245
|
-
def
|
245
|
+
def test_should_deep_clone_joined_association
|
246
246
|
subject1 = Subject.create(:name => 'subject 1')
|
247
247
|
subject2 = Subject.create(:name => 'subject 2')
|
248
248
|
student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
|
249
249
|
|
250
|
-
|
251
|
-
|
252
|
-
assert_equal 2,
|
253
|
-
[subject1, subject2].each{|subject| assert !
|
250
|
+
deep_clone = student.deep_clone :include => { :student_assignments => :subject }
|
251
|
+
deep_clone.save # Subjects will have been set after save
|
252
|
+
assert_equal 2, deep_clone.subjects.size
|
253
|
+
[subject1, subject2].each{|subject| assert !deep_clone.subjects.include?(subject) }
|
254
254
|
end
|
255
255
|
|
256
256
|
def test_parent_validations_run_on_save_after_clone
|
@@ -258,13 +258,13 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
258
258
|
parent = ParentWithValidation.new :children => [child]
|
259
259
|
parent.save :validate => false
|
260
260
|
|
261
|
-
|
261
|
+
deep_clone_parent = parent.deep_clone :include => :children
|
262
262
|
|
263
|
-
assert !
|
264
|
-
assert
|
265
|
-
assert !
|
266
|
-
assert
|
267
|
-
assert_equal
|
263
|
+
assert !deep_clone_parent.save
|
264
|
+
assert deep_clone_parent.new_record?
|
265
|
+
assert !deep_clone_parent.valid?
|
266
|
+
assert deep_clone_parent.children.first.valid?
|
267
|
+
assert_equal deep_clone_parent.errors.messages, :name => ["can't be blank"]
|
268
268
|
end
|
269
269
|
|
270
270
|
def test_parent_validations_dont_run_on_save_after_clone
|
@@ -272,13 +272,13 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
272
272
|
parent = ParentWithValidation.new :children => [child]
|
273
273
|
parent.save :validate => false
|
274
274
|
|
275
|
-
|
275
|
+
deep_clone_parent = parent.deep_clone :include => :children, :validate => false
|
276
276
|
|
277
|
-
assert
|
278
|
-
assert !
|
279
|
-
assert !
|
280
|
-
assert
|
281
|
-
assert_equal
|
277
|
+
assert deep_clone_parent.save
|
278
|
+
assert !deep_clone_parent.new_record?
|
279
|
+
assert !deep_clone_parent.valid?
|
280
|
+
assert deep_clone_parent.children.first.valid?
|
281
|
+
assert_equal deep_clone_parent.errors.messages, :name => ["can't be blank"]
|
282
282
|
end
|
283
283
|
|
284
284
|
def test_child_validations_run_on_save_after_clone
|
@@ -286,13 +286,13 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
286
286
|
child.save :validate => false
|
287
287
|
parent = ParentWithValidation.create :name => 'John', :children => [child]
|
288
288
|
|
289
|
-
|
289
|
+
deep_clone_parent = parent.deep_clone :include => :children
|
290
290
|
|
291
|
-
assert !
|
292
|
-
assert
|
293
|
-
assert !
|
294
|
-
assert !
|
295
|
-
assert_equal
|
291
|
+
assert !deep_clone_parent.save
|
292
|
+
assert deep_clone_parent.new_record?
|
293
|
+
assert !deep_clone_parent.valid?
|
294
|
+
assert !deep_clone_parent.children.first.valid?
|
295
|
+
assert_equal deep_clone_parent.errors.messages, :children => ["is invalid"]
|
296
296
|
end
|
297
297
|
|
298
298
|
def test_child_validations_run_on_save_after_clone
|
@@ -300,13 +300,13 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
300
300
|
child.save :validate => false
|
301
301
|
parent = ParentWithValidation.create :name => 'John', :children => [child]
|
302
302
|
|
303
|
-
|
303
|
+
deep_clone_parent = parent.deep_clone :include => :children, :validate => false
|
304
304
|
|
305
|
-
assert
|
306
|
-
assert !
|
307
|
-
assert !
|
308
|
-
assert !
|
309
|
-
assert_equal
|
305
|
+
assert deep_clone_parent.save
|
306
|
+
assert !deep_clone_parent.new_record?
|
307
|
+
assert !deep_clone_parent.valid?
|
308
|
+
assert !deep_clone_parent.children.first.valid?
|
309
|
+
assert_equal deep_clone_parent.errors.messages, :children => ["is invalid"]
|
310
310
|
end
|
311
311
|
|
312
312
|
def test_self_join_has_many
|
@@ -314,9 +314,9 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
314
314
|
child1 = Part.create(:name => 'Child 1', :parent_part_id => parent_part.id)
|
315
315
|
child2 = Part.create(:name => 'Child 2', :parent_part_id => parent_part.id)
|
316
316
|
|
317
|
-
|
318
|
-
assert
|
319
|
-
assert_equal 2,
|
317
|
+
deep_clone_part = parent_part.deep_clone :include => :child_parts
|
318
|
+
assert deep_clone_part.save
|
319
|
+
assert_equal 2, deep_clone_part.child_parts.size
|
320
320
|
end
|
321
321
|
|
322
322
|
def test_should_include_has_many_through_associations
|
@@ -324,9 +324,30 @@ class TestDeepCloneable < MiniTest::Unit::TestCase
|
|
324
324
|
subject2 = Subject.create(:name => 'subject 2')
|
325
325
|
student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
|
326
326
|
|
327
|
-
|
328
|
-
assert_equal 2,
|
329
|
-
assert_equal [[student,
|
327
|
+
deep_clone = student.deep_clone :include => :subjects
|
328
|
+
assert_equal 2, deep_clone.subjects.size
|
329
|
+
assert_equal [[student, deep_clone],[student, deep_clone]], deep_clone.subjects.map{|subject| subject.students }
|
330
|
+
end
|
331
|
+
|
332
|
+
def test_should_deep_clone_unsaved_objects
|
333
|
+
jack = Pirate.new(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
|
334
|
+
jack.mateys.build(:name => 'John')
|
335
|
+
|
336
|
+
deep_clone = jack.deep_clone(:include => :mateys)
|
337
|
+
assert deep_clone.new_record?
|
338
|
+
assert_equal 1, deep_clone.mateys.size
|
339
|
+
assert_equal 'John', deep_clone.mateys.first.name
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_should_deep_clone_via_dup
|
343
|
+
deep_clone = @jack.dup(:include => :parrot) do |original, kopy|
|
344
|
+
kopy.cloned_from_id = original.id
|
345
|
+
end
|
346
|
+
|
347
|
+
assert deep_clone.new_record?
|
348
|
+
assert deep_clone.save
|
349
|
+
assert_equal @jack.id, deep_clone.cloned_from_id
|
350
|
+
assert_equal @jack.parrot.id, deep_clone.parrot.cloned_from_id
|
330
351
|
end
|
331
352
|
|
332
353
|
end
|
metadata
CHANGED
@@ -1,31 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep_cloneable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reinier de Lange
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
14
15
|
requirement: !ruby/object:Gem::Requirement
|
15
16
|
requirements:
|
16
|
-
- -
|
17
|
+
- - ">="
|
17
18
|
- !ruby/object:Gem::Version
|
18
19
|
version: 3.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
19
22
|
version_requirements: !ruby/object:Gem::Requirement
|
20
23
|
requirements:
|
21
|
-
- -
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
22
32
|
- !ruby/object:Gem::Version
|
23
33
|
version: 3.1.0
|
24
34
|
type: :runtime
|
25
35
|
prerelease: false
|
26
|
-
|
27
|
-
|
28
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.1.0
|
41
|
+
description: 'Extends the functionality of ActiveRecord::Base#clone to perform a deep
|
42
|
+
clone that includes user specified associations. '
|
29
43
|
email: r.j.delange@nedforce.nl
|
30
44
|
executables: []
|
31
45
|
extensions: []
|
@@ -33,8 +47,8 @@ extra_rdoc_files:
|
|
33
47
|
- LICENSE
|
34
48
|
- README.rdoc
|
35
49
|
files:
|
36
|
-
- .document
|
37
|
-
- .travis.yml
|
50
|
+
- ".document"
|
51
|
+
- ".travis.yml"
|
38
52
|
- Appraisals
|
39
53
|
- Gemfile
|
40
54
|
- Gemfile.lock
|
@@ -67,17 +81,17 @@ require_paths:
|
|
67
81
|
- lib
|
68
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
83
|
requirements:
|
70
|
-
- -
|
84
|
+
- - ">="
|
71
85
|
- !ruby/object:Gem::Version
|
72
86
|
version: '0'
|
73
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
88
|
requirements:
|
75
|
-
- -
|
89
|
+
- - ">="
|
76
90
|
- !ruby/object:Gem::Version
|
77
91
|
version: '0'
|
78
92
|
requirements: []
|
79
93
|
rubyforge_project:
|
80
|
-
rubygems_version: 2.
|
94
|
+
rubygems_version: 2.2.2
|
81
95
|
signing_key:
|
82
96
|
specification_version: 4
|
83
97
|
summary: This gem gives every ActiveRecord::Base object the possibility to do a deep
|