deep_cloneable 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +10 -0
- data/Appraisals +11 -0
- data/Gemfile +5 -8
- data/Gemfile.lock +18 -14
- data/README.rdoc +7 -3
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/deep_cloneable.gemspec +21 -7
- data/gemfiles/3.0.gemfile +9 -0
- data/gemfiles/3.0.gemfile.lock +42 -0
- data/gemfiles/3.1.gemfile +9 -0
- data/gemfiles/3.1.gemfile.lock +42 -0
- data/gemfiles/3.2.gemfile +9 -0
- data/gemfiles/3.2.gemfile.lock +42 -0
- data/lib/deep_cloneable.rb +60 -35
- data/test/models.rb +20 -0
- data/test/schema.rb +17 -0
- data/test/test_deep_cloneable.rb +40 -22
- data/test/test_helper.rb +1 -0
- metadata +47 -7
data/.travis.yml
ADDED
data/Appraisals
ADDED
data/Gemfile
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
|
-
gem '
|
3
|
+
gem 'appraisal'
|
4
|
+
gem 'activerecord', '>= 3.2'
|
5
|
+
gem 'jeweler'
|
6
|
+
gem 'sqlite3'
|
4
7
|
|
5
|
-
|
6
|
-
gem 'jeweler'
|
7
|
-
end
|
8
|
-
|
9
|
-
group :test do
|
10
|
-
gem 'sqlite3'
|
11
|
-
end
|
8
|
+
# gem 'debugger'
|
data/Gemfile.lock
CHANGED
@@ -1,38 +1,42 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.2.
|
5
|
-
activesupport (= 3.2.
|
4
|
+
activemodel (3.2.13)
|
5
|
+
activesupport (= 3.2.13)
|
6
6
|
builder (~> 3.0.0)
|
7
|
-
activerecord (3.2.
|
8
|
-
activemodel (= 3.2.
|
9
|
-
activesupport (= 3.2.
|
7
|
+
activerecord (3.2.13)
|
8
|
+
activemodel (= 3.2.13)
|
9
|
+
activesupport (= 3.2.13)
|
10
10
|
arel (~> 3.0.2)
|
11
11
|
tzinfo (~> 0.3.29)
|
12
|
-
activesupport (3.2.
|
13
|
-
i18n (
|
12
|
+
activesupport (3.2.13)
|
13
|
+
i18n (= 0.6.1)
|
14
14
|
multi_json (~> 1.0)
|
15
|
+
appraisal (0.5.2)
|
16
|
+
bundler
|
17
|
+
rake
|
15
18
|
arel (3.0.2)
|
16
19
|
builder (3.0.4)
|
17
20
|
git (1.2.5)
|
18
|
-
i18n (0.6.
|
21
|
+
i18n (0.6.1)
|
19
22
|
jeweler (1.8.4)
|
20
23
|
bundler (~> 1.0)
|
21
24
|
git (>= 1.2.5)
|
22
25
|
rake
|
23
26
|
rdoc
|
24
|
-
json (1.
|
25
|
-
multi_json (1.
|
26
|
-
rake (10.0.
|
27
|
-
rdoc (4.0.
|
27
|
+
json (1.8.0)
|
28
|
+
multi_json (1.7.3)
|
29
|
+
rake (10.0.4)
|
30
|
+
rdoc (4.0.1)
|
28
31
|
json (~> 1.4)
|
29
32
|
sqlite3 (1.3.7)
|
30
|
-
tzinfo (0.3.
|
33
|
+
tzinfo (0.3.37)
|
31
34
|
|
32
35
|
PLATFORMS
|
33
36
|
ruby
|
34
37
|
|
35
38
|
DEPENDENCIES
|
36
|
-
activerecord (>= 3.
|
39
|
+
activerecord (>= 3.2)
|
40
|
+
appraisal
|
37
41
|
jeweler
|
38
42
|
sqlite3
|
data/README.rdoc
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
= Deep_cloneable
|
2
2
|
|
3
|
+
{<img src="https://travis-ci.org/moiristo/deep_cloneable.png?branch=master" alt="Build Status" />}[https://travis-ci.org/moiristo/deep_cloneable]
|
4
|
+
|
3
5
|
This gem gives every ActiveRecord::Base object the possibility to do a deep clone. It is a rails3 upgrade of the deep_cloning plugin (http://github.com/openminds/deep_cloning).
|
4
6
|
|
5
7
|
== Requirements
|
6
8
|
|
7
|
-
* Ruby 1.8.7, 1.9, 2.0.0
|
9
|
+
* Ruby 1.8.7, 1.9.3, 2.0.0
|
8
10
|
|
9
|
-
* Activerecord 3.1, 3.2
|
11
|
+
* Activerecord 3.0 (when using _dup_), 3.1, 3.2
|
10
12
|
|
11
13
|
* Rails 2.x/3.0 users, please check out the 'rails2.x-3.0' branch.
|
12
14
|
|
@@ -14,7 +16,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
|
|
14
16
|
|
15
17
|
* In your Gemfile:
|
16
18
|
|
17
|
-
gem 'deep_cloneable', '~> 1.5.
|
19
|
+
gem 'deep_cloneable', '~> 1.5.2'
|
18
20
|
|
19
21
|
== Example
|
20
22
|
|
@@ -71,6 +73,8 @@ If this is not an option for you, it is also possible to populate the dictionary
|
|
71
73
|
* fractious
|
72
74
|
* Georges Gabereau
|
73
75
|
* Christophe Belpaire
|
76
|
+
* Kevin Carter
|
77
|
+
* fokcep
|
74
78
|
|
75
79
|
== Note on Patches/Pull Requests
|
76
80
|
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.5.
|
1
|
+
1.5.2
|
data/deep_cloneable.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "deep_cloneable"
|
8
|
-
s.version = "1.5.
|
8
|
+
s.version = "1.5.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Reinier de Lange"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-06-10"
|
13
13
|
s.description = "Extends the functionality of ActiveRecord::Base#clone to perform a deep clone that includes user specified associations. "
|
14
14
|
s.email = "r.j.delange@nedforce.nl"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".document",
|
21
|
+
".travis.yml",
|
22
|
+
"Appraisals",
|
21
23
|
"Gemfile",
|
22
24
|
"Gemfile.lock",
|
23
25
|
"LICENSE",
|
@@ -25,6 +27,12 @@ Gem::Specification.new do |s|
|
|
25
27
|
"Rakefile",
|
26
28
|
"VERSION",
|
27
29
|
"deep_cloneable.gemspec",
|
30
|
+
"gemfiles/3.0.gemfile",
|
31
|
+
"gemfiles/3.0.gemfile.lock",
|
32
|
+
"gemfiles/3.1.gemfile",
|
33
|
+
"gemfiles/3.1.gemfile.lock",
|
34
|
+
"gemfiles/3.2.gemfile",
|
35
|
+
"gemfiles/3.2.gemfile.lock",
|
28
36
|
"init.rb",
|
29
37
|
"lib/deep_cloneable.rb",
|
30
38
|
"test/database.yml",
|
@@ -35,22 +43,28 @@ Gem::Specification.new do |s|
|
|
35
43
|
]
|
36
44
|
s.homepage = "http://github.com/moiristo/deep_cloneable"
|
37
45
|
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = "1.8.
|
46
|
+
s.rubygems_version = "1.8.25"
|
39
47
|
s.summary = "This gem gives every ActiveRecord::Base object the possibility to do a deep clone."
|
40
48
|
|
41
49
|
if s.respond_to? :specification_version then
|
42
50
|
s.specification_version = 3
|
43
51
|
|
44
52
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
|
-
s.add_runtime_dependency(%q<
|
46
|
-
s.
|
53
|
+
s.add_runtime_dependency(%q<appraisal>, [">= 0"])
|
54
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 3.2"])
|
55
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
56
|
+
s.add_runtime_dependency(%q<sqlite3>, [">= 0"])
|
47
57
|
else
|
48
|
-
s.add_dependency(%q<
|
58
|
+
s.add_dependency(%q<appraisal>, [">= 0"])
|
59
|
+
s.add_dependency(%q<activerecord>, [">= 3.2"])
|
49
60
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
61
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
50
62
|
end
|
51
63
|
else
|
52
|
-
s.add_dependency(%q<
|
64
|
+
s.add_dependency(%q<appraisal>, [">= 0"])
|
65
|
+
s.add_dependency(%q<activerecord>, [">= 3.2"])
|
53
66
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
67
|
+
s.add_dependency(%q<sqlite3>, [">= 0"])
|
54
68
|
end
|
55
69
|
end
|
56
70
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.2.13)
|
5
|
+
activesupport (= 3.2.13)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activerecord (3.2.13)
|
8
|
+
activemodel (= 3.2.13)
|
9
|
+
activesupport (= 3.2.13)
|
10
|
+
arel (~> 3.0.2)
|
11
|
+
tzinfo (~> 0.3.29)
|
12
|
+
activesupport (3.2.13)
|
13
|
+
i18n (= 0.6.1)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
appraisal (0.5.2)
|
16
|
+
bundler
|
17
|
+
rake
|
18
|
+
arel (3.0.2)
|
19
|
+
builder (3.0.4)
|
20
|
+
git (1.2.5)
|
21
|
+
i18n (0.6.1)
|
22
|
+
jeweler (1.8.4)
|
23
|
+
bundler (~> 1.0)
|
24
|
+
git (>= 1.2.5)
|
25
|
+
rake
|
26
|
+
rdoc
|
27
|
+
json (1.8.0)
|
28
|
+
multi_json (1.7.3)
|
29
|
+
rake (10.0.4)
|
30
|
+
rdoc (4.0.1)
|
31
|
+
json (~> 1.4)
|
32
|
+
sqlite3 (1.3.7)
|
33
|
+
tzinfo (0.3.37)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
activerecord (~> 3.0)
|
40
|
+
appraisal
|
41
|
+
jeweler
|
42
|
+
sqlite3
|
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.2.13)
|
5
|
+
activesupport (= 3.2.13)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activerecord (3.2.13)
|
8
|
+
activemodel (= 3.2.13)
|
9
|
+
activesupport (= 3.2.13)
|
10
|
+
arel (~> 3.0.2)
|
11
|
+
tzinfo (~> 0.3.29)
|
12
|
+
activesupport (3.2.13)
|
13
|
+
i18n (= 0.6.1)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
appraisal (0.5.2)
|
16
|
+
bundler
|
17
|
+
rake
|
18
|
+
arel (3.0.2)
|
19
|
+
builder (3.0.4)
|
20
|
+
git (1.2.5)
|
21
|
+
i18n (0.6.1)
|
22
|
+
jeweler (1.8.4)
|
23
|
+
bundler (~> 1.0)
|
24
|
+
git (>= 1.2.5)
|
25
|
+
rake
|
26
|
+
rdoc
|
27
|
+
json (1.8.0)
|
28
|
+
multi_json (1.7.3)
|
29
|
+
rake (10.0.4)
|
30
|
+
rdoc (4.0.1)
|
31
|
+
json (~> 1.4)
|
32
|
+
sqlite3 (1.3.7)
|
33
|
+
tzinfo (0.3.37)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
activerecord (~> 3.1)
|
40
|
+
appraisal
|
41
|
+
jeweler
|
42
|
+
sqlite3
|
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.2.13)
|
5
|
+
activesupport (= 3.2.13)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activerecord (3.2.13)
|
8
|
+
activemodel (= 3.2.13)
|
9
|
+
activesupport (= 3.2.13)
|
10
|
+
arel (~> 3.0.2)
|
11
|
+
tzinfo (~> 0.3.29)
|
12
|
+
activesupport (3.2.13)
|
13
|
+
i18n (= 0.6.1)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
appraisal (0.5.2)
|
16
|
+
bundler
|
17
|
+
rake
|
18
|
+
arel (3.0.2)
|
19
|
+
builder (3.0.4)
|
20
|
+
git (1.2.5)
|
21
|
+
i18n (0.6.1)
|
22
|
+
jeweler (1.8.4)
|
23
|
+
bundler (~> 1.0)
|
24
|
+
git (>= 1.2.5)
|
25
|
+
rake
|
26
|
+
rdoc
|
27
|
+
json (1.8.0)
|
28
|
+
multi_json (1.7.3)
|
29
|
+
rake (10.0.4)
|
30
|
+
rdoc (4.0.1)
|
31
|
+
json (~> 1.4)
|
32
|
+
sqlite3 (1.3.7)
|
33
|
+
tzinfo (0.3.37)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
activerecord (~> 3.2)
|
40
|
+
appraisal
|
41
|
+
jeweler
|
42
|
+
sqlite3
|
data/lib/deep_cloneable.rb
CHANGED
@@ -3,12 +3,12 @@ class ActiveRecord::Base
|
|
3
3
|
# ActiveRecord::Base has its own dup method for Ruby 1.8.7. We have to
|
4
4
|
# redefine it and put it in a module so that we can override it in a
|
5
5
|
# module and call the original with super().
|
6
|
-
|
6
|
+
unless Object.respond_to?(:initialize_dup, true)
|
7
7
|
ActiveRecord::Base.class_eval do
|
8
8
|
module Dup
|
9
9
|
def dup
|
10
10
|
copy = super
|
11
|
-
copy.initialize_dup
|
11
|
+
copy.send(:initialize_dup, self)
|
12
12
|
copy
|
13
13
|
end
|
14
14
|
end
|
@@ -57,7 +57,7 @@ class ActiveRecord::Base
|
|
57
57
|
# ==== Cloning a model without an attribute or nested multiple attributes
|
58
58
|
# pirate.clone :include => :parrot, :except => [:name, { :parrot => [:name] }]
|
59
59
|
#
|
60
|
-
|
60
|
+
def dup *args, &block
|
61
61
|
options = args[0] || {}
|
62
62
|
|
63
63
|
dict = options[:dictionary]
|
@@ -89,9 +89,9 @@ class ActiveRecord::Base
|
|
89
89
|
association = association.keys.first
|
90
90
|
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
dup_options = deep_associations.blank? ? {} : {:include => deep_associations}
|
93
|
+
dup_options.merge!(:except => deep_exceptions[association]) if deep_exceptions[association]
|
94
|
+
dup_options.merge!(:dictionary => dict) if dict
|
95
95
|
|
96
96
|
association_reflection = self.class.reflect_on_association(association)
|
97
97
|
raise AssociationNotFoundException.new("#{self.class}##{association}") if association_reflection.nil?
|
@@ -106,34 +106,11 @@ class ActiveRecord::Base
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
cloned_object =
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
|
116
|
-
a.foreign_key.to_s == primary_key_name
|
117
|
-
end.try(:name)
|
118
|
-
|
119
|
-
self.send(association).collect do |obj|
|
120
|
-
tmp = obj.send(__method__, opts, &block)
|
121
|
-
tmp.send("#{primary_key_name}=", nil)
|
122
|
-
tmp.send("#{reverse_association_name.to_s}=", kopy) if reverse_association_name
|
123
|
-
tmp
|
124
|
-
end
|
125
|
-
when :has_and_belongs_to_many
|
126
|
-
primary_key_name = association_reflection.foreign_key.to_s
|
127
|
-
|
128
|
-
reverse_association_name = association_reflection.klass.reflect_on_all_associations.detect do |a|
|
129
|
-
(a.macro == :has_and_belongs_to_many) && (a.association_foreign_key.to_s == primary_key_name)
|
130
|
-
end.try(:name)
|
131
|
-
|
132
|
-
self.send(association).collect do |obj|
|
133
|
-
obj.send(reverse_association_name).target << kopy
|
134
|
-
obj
|
135
|
-
end
|
136
|
-
end
|
109
|
+
cloned_object = send(
|
110
|
+
"dup_#{association_reflection.macro}_#{association_reflection.class.name.demodulize.underscore.gsub('_reflection', '')}",
|
111
|
+
{ :reflection => association_reflection, :association => association, :copy => kopy, :dup_options => dup_options },
|
112
|
+
&block
|
113
|
+
)
|
137
114
|
|
138
115
|
kopy.send("#{association}=", cloned_object)
|
139
116
|
end
|
@@ -141,7 +118,55 @@ class ActiveRecord::Base
|
|
141
118
|
|
142
119
|
return kopy
|
143
120
|
end
|
144
|
-
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def dup_belongs_to_association options, &block
|
125
|
+
self.send(options[:association]) && self.send(options[:association]).dup(options[:dup_options], &block)
|
126
|
+
end
|
127
|
+
|
128
|
+
def dup_has_one_association options, &block
|
129
|
+
dup_belongs_to_association options, &block
|
130
|
+
end
|
131
|
+
|
132
|
+
def dup_has_many_association options, &block
|
133
|
+
primary_key_name = options[:reflection].foreign_key.to_s
|
134
|
+
|
135
|
+
reverse_association_name = options[:reflection].klass.reflect_on_all_associations.detect do |reflection|
|
136
|
+
reflection.foreign_key.to_s == primary_key_name && reflection != options[:reflection]
|
137
|
+
end.try(:name)
|
138
|
+
|
139
|
+
self.send(options[:association]).collect do |obj|
|
140
|
+
tmp = obj.dup(options[:dup_options], &block)
|
141
|
+
tmp.send("#{primary_key_name}=", nil)
|
142
|
+
tmp.send("#{reverse_association_name.to_s}=", options[:copy]) if reverse_association_name
|
143
|
+
tmp
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def dup_has_many_through options, &block
|
148
|
+
dup_join_association(
|
149
|
+
options.merge(:macro => :has_many, :primary_key_name => options[:reflection].through_reflection.foreign_key.to_s),
|
150
|
+
&block)
|
151
|
+
end
|
152
|
+
|
153
|
+
def dup_has_and_belongs_to_many_association options, &block
|
154
|
+
dup_join_association(
|
155
|
+
options.merge(:macro => :has_and_belongs_to_many, :primary_key_name => options[:reflection].foreign_key.to_s),
|
156
|
+
&block)
|
157
|
+
end
|
158
|
+
|
159
|
+
def dup_join_association options, &block
|
160
|
+
reverse_association_name = options[:reflection].klass.reflect_on_all_associations.detect do |reflection|
|
161
|
+
(reflection.macro == options[:macro]) && (reflection.association_foreign_key.to_s == options[:primary_key_name])
|
162
|
+
end.try(:name)
|
163
|
+
|
164
|
+
self.send(options[:association]).collect do |obj|
|
165
|
+
obj.send(reverse_association_name).target << options[:copy]
|
166
|
+
obj
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
145
170
|
class AssociationNotFoundException < StandardError; end
|
146
171
|
end
|
147
172
|
|
data/test/models.rb
CHANGED
@@ -62,3 +62,23 @@ class ParentWithValidation < ActiveRecord::Base
|
|
62
62
|
has_many :children, :class_name => 'ChildWithValidation'
|
63
63
|
validates :name, :presence => true
|
64
64
|
end
|
65
|
+
|
66
|
+
class Part < ActiveRecord::Base
|
67
|
+
# belongs_to :parent_part, :class_name => 'Part'
|
68
|
+
has_many :child_parts, :class_name => 'Part', :foreign_key => 'parent_part_id'
|
69
|
+
end
|
70
|
+
|
71
|
+
class Student < ActiveRecord::Base
|
72
|
+
has_many :student_assignments, :dependent => :destroy
|
73
|
+
has_many :subjects, :through => :student_assignments
|
74
|
+
end
|
75
|
+
|
76
|
+
class Subject < ActiveRecord::Base
|
77
|
+
has_many :student_assignments, :dependent => :destroy
|
78
|
+
has_many :students, :through => :student_assignments
|
79
|
+
end
|
80
|
+
|
81
|
+
class StudentAssignment < ActiveRecord::Base
|
82
|
+
belongs_to :subject
|
83
|
+
belongs_to :student
|
84
|
+
end
|
data/test/schema.rb
CHANGED
@@ -71,4 +71,21 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
71
71
|
t.column :parent_with_validation_id, :integer
|
72
72
|
end
|
73
73
|
|
74
|
+
create_table :parts, :force => true do |t|
|
75
|
+
t.column :name, :string
|
76
|
+
t.column :parent_part_id, :integer
|
77
|
+
end
|
78
|
+
|
79
|
+
create_table :students, :force => true do |t|
|
80
|
+
t.column :name, :string
|
81
|
+
end
|
82
|
+
|
83
|
+
create_table :subjects, :force => true do |t|
|
84
|
+
t.column :name, :string
|
85
|
+
end
|
86
|
+
|
87
|
+
create_table :student_assignments, :force => true do |t|
|
88
|
+
t.column :student_id, :integer
|
89
|
+
t.column :subject_id, :integer
|
90
|
+
end
|
74
91
|
end
|
data/test/test_deep_cloneable.rb
CHANGED
@@ -3,8 +3,6 @@ require File.dirname(__FILE__) + '/test_helper'
|
|
3
3
|
class TestDeepCloneable < Test::Unit::TestCase
|
4
4
|
load_schema
|
5
5
|
|
6
|
-
@@clone_method = ActiveRecord::VERSION::MAJOR >= 3 && ActiveRecord::VERSION::MINOR > 0 ? :dup : :clone
|
7
|
-
|
8
6
|
def setup
|
9
7
|
@jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
|
10
8
|
@polly = Parrot.create(:name => 'Polly', :pirate => @jack)
|
@@ -15,16 +13,16 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
15
13
|
end
|
16
14
|
|
17
15
|
def test_single_dup_exception
|
18
|
-
dup = @jack.
|
16
|
+
dup = @jack.dup(:except => :name)
|
19
17
|
assert dup.new_record?
|
20
18
|
assert dup.save
|
21
|
-
assert_equal @jack.name, @jack.
|
19
|
+
assert_equal @jack.name, @jack.dup.name
|
22
20
|
assert_nil dup.name
|
23
21
|
assert_equal @jack.nick_name, dup.nick_name
|
24
22
|
end
|
25
23
|
|
26
24
|
def test_multiple_dup_exception
|
27
|
-
dup = @jack.
|
25
|
+
dup = @jack.dup(:except => [:name, :nick_name])
|
28
26
|
assert dup.new_record?
|
29
27
|
assert dup.save
|
30
28
|
assert_nil dup.name
|
@@ -33,14 +31,14 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
33
31
|
end
|
34
32
|
|
35
33
|
def test_single_include_association
|
36
|
-
dup = @jack.
|
34
|
+
dup = @jack.dup(:include => :mateys)
|
37
35
|
assert dup.new_record?
|
38
36
|
assert dup.save
|
39
37
|
assert_equal 1, dup.mateys.size
|
40
38
|
end
|
41
39
|
|
42
40
|
def test_single_include_belongs_to_polymorphic_association
|
43
|
-
dup = @jack.
|
41
|
+
dup = @jack.dup(:include => :ship)
|
44
42
|
assert dup.new_record?
|
45
43
|
assert dup.save
|
46
44
|
assert_not_nil dup.ship
|
@@ -48,14 +46,14 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
48
46
|
end
|
49
47
|
|
50
48
|
def test_single_include_has_many_polymorphic_association
|
51
|
-
dup = @ship.
|
49
|
+
dup = @ship.dup(:include => :pirates)
|
52
50
|
assert dup.new_record?
|
53
51
|
assert dup.save
|
54
52
|
assert dup.pirates.any?
|
55
53
|
end
|
56
54
|
|
57
55
|
def test_multiple_include_association
|
58
|
-
dup = @jack.
|
56
|
+
dup = @jack.dup(:include => [:mateys, :treasures])
|
59
57
|
assert dup.new_record?
|
60
58
|
assert dup.save
|
61
59
|
assert_equal 1, dup.mateys.size
|
@@ -63,7 +61,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
63
61
|
end
|
64
62
|
|
65
63
|
def test_deep_include_association
|
66
|
-
dup = @jack.
|
64
|
+
dup = @jack.dup(:include => {:treasures => :gold_pieces})
|
67
65
|
assert dup.new_record?
|
68
66
|
assert dup.save
|
69
67
|
assert_equal 1, dup.treasures.size
|
@@ -71,7 +69,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
71
69
|
end
|
72
70
|
|
73
71
|
def test_include_association_assignments
|
74
|
-
dup = @jack.
|
72
|
+
dup = @jack.dup(:include => :treasures)
|
75
73
|
assert dup.new_record?
|
76
74
|
|
77
75
|
dup.treasures.each do |treasure|
|
@@ -80,7 +78,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
80
78
|
end
|
81
79
|
|
82
80
|
def test_multiple_and_deep_include_association
|
83
|
-
dup = @jack.
|
81
|
+
dup = @jack.dup(:include => {:treasures => :gold_pieces, :mateys => {}})
|
84
82
|
assert dup.new_record?
|
85
83
|
assert dup.save
|
86
84
|
assert_equal 1, dup.treasures.size
|
@@ -89,7 +87,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
89
87
|
end
|
90
88
|
|
91
89
|
def test_multiple_and_deep_include_association_with_array
|
92
|
-
dup = @jack.
|
90
|
+
dup = @jack.dup(:include => [{:treasures => :gold_pieces}, :mateys])
|
93
91
|
assert dup.new_record?
|
94
92
|
assert dup.save
|
95
93
|
assert_equal 1, dup.treasures.size
|
@@ -98,14 +96,14 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
98
96
|
end
|
99
97
|
|
100
98
|
def test_with_belongs_to_relation
|
101
|
-
dup = @jack.
|
99
|
+
dup = @jack.dup(:include => :parrot)
|
102
100
|
assert dup.new_record?
|
103
101
|
assert dup.save
|
104
102
|
assert_not_equal dup.parrot, @jack.parrot
|
105
103
|
end
|
106
104
|
|
107
105
|
def test_should_pass_nested_exceptions
|
108
|
-
dup = @jack.
|
106
|
+
dup = @jack.dup(:include => :parrot, :except => [:name, { :parrot => [:name] }])
|
109
107
|
assert dup.new_record?
|
110
108
|
assert dup.save
|
111
109
|
assert_not_equal dup.parrot, @jack.parrot
|
@@ -115,7 +113,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
115
113
|
|
116
114
|
def test_should_not_double_dup_when_using_dictionary
|
117
115
|
current_matey_count = Matey.count
|
118
|
-
dup = @jack.
|
116
|
+
dup = @jack.dup(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
|
119
117
|
assert dup.new_record?
|
120
118
|
dup.save!
|
121
119
|
|
@@ -126,9 +124,9 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
126
124
|
current_matey_count = Matey.count
|
127
125
|
|
128
126
|
dict = { :mateys => {} }
|
129
|
-
@jack.mateys.each{|m| dict[:mateys][m] = m.
|
127
|
+
@jack.mateys.each{|m| dict[:mateys][m] = m.dup }
|
130
128
|
|
131
|
-
dup = @jack.
|
129
|
+
dup = @jack.dup(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
|
132
130
|
assert dup.new_record?
|
133
131
|
dup.save!
|
134
132
|
|
@@ -139,7 +137,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
139
137
|
@human = Animal::Human.create :name => "Michael"
|
140
138
|
@pig = Animal::Pig.create :human => @human, :name => 'big pig'
|
141
139
|
|
142
|
-
dup_human = @human.
|
140
|
+
dup_human = @human.dup(:include => [:pigs])
|
143
141
|
assert dup_human.new_record?
|
144
142
|
assert dup_human.save
|
145
143
|
assert_equal 1, dup_human.pigs.count
|
@@ -147,7 +145,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
147
145
|
@human2 = Animal::Human.create :name => "John"
|
148
146
|
@pig2 = @human2.pigs.create :name => 'small pig'
|
149
147
|
|
150
|
-
dup_human_2 = @human.
|
148
|
+
dup_human_2 = @human.dup(:include => [:pigs])
|
151
149
|
assert dup_human_2.new_record?
|
152
150
|
assert dup_human_2.save
|
153
151
|
assert_equal 1, dup_human_2.pigs.count
|
@@ -161,14 +159,14 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
161
159
|
@human.chickens << [@chicken1, @chicken2]
|
162
160
|
@human2.chickens << [@chicken1, @chicken2]
|
163
161
|
|
164
|
-
dup_human = @human.
|
162
|
+
dup_human = @human.dup(:include => :ownerships)
|
165
163
|
assert dup_human.new_record?
|
166
164
|
assert dup_human.save
|
167
165
|
assert_equal 2, dup_human.chickens.count
|
168
166
|
end
|
169
167
|
|
170
168
|
def test_should_dup_with_block
|
171
|
-
dup = @jack.
|
169
|
+
dup = @jack.dup(:include => :parrot) do |original, kopy|
|
172
170
|
kopy.cloned_from_id = original.id
|
173
171
|
end
|
174
172
|
|
@@ -258,4 +256,24 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
258
256
|
assert_equal dup_parent.errors.messages, :children => ["is invalid"]
|
259
257
|
end
|
260
258
|
|
259
|
+
def test_self_join_has_many
|
260
|
+
parent_part = Part.create(:name => 'Parent')
|
261
|
+
child1 = Part.create(:name => 'Child 1', :parent_part_id => parent_part.id)
|
262
|
+
child2 = Part.create(:name => 'Child 2', :parent_part_id => parent_part.id)
|
263
|
+
|
264
|
+
dup_part = parent_part.dup :include => :child_parts
|
265
|
+
assert dup_part.save
|
266
|
+
assert_equal 2, dup_part.child_parts.size
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_should_include_has_many_through_associations
|
270
|
+
subject1 = Subject.create(:name => 'subject 1')
|
271
|
+
subject2 = Subject.create(:name => 'subject 2')
|
272
|
+
student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
|
273
|
+
|
274
|
+
dup = student.dup :include => :subjects
|
275
|
+
assert_equal 2, dup.subjects.size
|
276
|
+
assert_equal [[student, dup],[student, dup]], dup.subjects.map{|subject| subject.students }
|
277
|
+
end
|
278
|
+
|
261
279
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep_cloneable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: appraisal
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: activerecord
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -18,7 +34,7 @@ dependencies:
|
|
18
34
|
requirements:
|
19
35
|
- - ! '>='
|
20
36
|
- !ruby/object:Gem::Version
|
21
|
-
version: '3.
|
37
|
+
version: '3.2'
|
22
38
|
type: :runtime
|
23
39
|
prerelease: false
|
24
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +42,7 @@ dependencies:
|
|
26
42
|
requirements:
|
27
43
|
- - ! '>='
|
28
44
|
- !ruby/object:Gem::Version
|
29
|
-
version: '3.
|
45
|
+
version: '3.2'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: jeweler
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -35,7 +51,23 @@ dependencies:
|
|
35
51
|
- - ! '>='
|
36
52
|
- !ruby/object:Gem::Version
|
37
53
|
version: '0'
|
38
|
-
type: :
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: sqlite3
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
39
71
|
prerelease: false
|
40
72
|
version_requirements: !ruby/object:Gem::Requirement
|
41
73
|
none: false
|
@@ -53,6 +85,8 @@ extra_rdoc_files:
|
|
53
85
|
- README.rdoc
|
54
86
|
files:
|
55
87
|
- .document
|
88
|
+
- .travis.yml
|
89
|
+
- Appraisals
|
56
90
|
- Gemfile
|
57
91
|
- Gemfile.lock
|
58
92
|
- LICENSE
|
@@ -60,6 +94,12 @@ files:
|
|
60
94
|
- Rakefile
|
61
95
|
- VERSION
|
62
96
|
- deep_cloneable.gemspec
|
97
|
+
- gemfiles/3.0.gemfile
|
98
|
+
- gemfiles/3.0.gemfile.lock
|
99
|
+
- gemfiles/3.1.gemfile
|
100
|
+
- gemfiles/3.1.gemfile.lock
|
101
|
+
- gemfiles/3.2.gemfile
|
102
|
+
- gemfiles/3.2.gemfile.lock
|
63
103
|
- init.rb
|
64
104
|
- lib/deep_cloneable.rb
|
65
105
|
- test/database.yml
|
@@ -81,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
81
121
|
version: '0'
|
82
122
|
segments:
|
83
123
|
- 0
|
84
|
-
hash:
|
124
|
+
hash: -3147244194353225191
|
85
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
126
|
none: false
|
87
127
|
requirements:
|
@@ -90,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
130
|
version: '0'
|
91
131
|
requirements: []
|
92
132
|
rubyforge_project:
|
93
|
-
rubygems_version: 1.8.
|
133
|
+
rubygems_version: 1.8.25
|
94
134
|
signing_key:
|
95
135
|
specification_version: 3
|
96
136
|
summary: This gem gives every ActiveRecord::Base object the possibility to do a deep
|