deep_cloneable 1.5.1 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|