deep_cloneable 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +9 -4
- data/Appraisals +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -0
- data/LICENSE +1 -1
- data/README.rdoc +14 -14
- data/VERSION +1 -1
- data/deep_cloneable.gemspec +4 -2
- data/gemfiles/3.1.gemfile +1 -0
- data/gemfiles/3.1.gemfile.lock +2 -0
- data/gemfiles/3.2.gemfile +1 -0
- data/gemfiles/3.2.gemfile.lock +2 -0
- data/gemfiles/4.0.gemfile +1 -0
- data/gemfiles/4.0.gemfile.lock +1 -0
- data/gemfiles/4.1.gemfile +11 -0
- data/gemfiles/4.1.gemfile.lock +44 -0
- data/lib/deep_cloneable.rb +16 -16
- data/test/models.rb +7 -3
- data/test/schema.rb +13 -4
- data/test/test_deep_cloneable.rb +22 -11
- data/test/test_helper.rb +9 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NGNlZTg5YzA1YjhiNmFmZjI4ZDBjZTIxYmJkYTZjYjZhZjE5MWQzNA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTNiYjYzMmI2YmMzOGY1NGEyNWE4ZmMzZWExNTE3NjJmYzc0ZjJkMQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODQ0NDJiMzkwMzY5YzNlYmMyNjc1NTlmZTIxOWNiMDcyNjg1NWJiOGYyMGJh
|
10
|
+
N2I4NDY3YWNiZmRhNjkyNTExMDMwYzBlNWZhMTEyODk0ZmM0ZGNkZDMzZmQw
|
11
|
+
MDIzYjI3OTdlYmEyOWMzNWRmZTQzZjU3NTU0NDc2MjI0NTk4NGE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YzhkMmVkYWQxYjk1MDhhMTU0MTlmNjNjNGI4NTZiNTc2M2FiZWVjOGVkNTZh
|
14
|
+
NDI3NGU0YjUzMjFkNzZlNWRjMmY0ODhlZmI0MzBjZjM0M2YzNjczZjQzZWY0
|
15
|
+
ZGVjNGU0OGEzYWQ1MDYxM2E1Njc5ZDU4Y2NlYzA2OTY2OWFjY2I=
|
data/.travis.yml
CHANGED
@@ -3,15 +3,20 @@ rvm:
|
|
3
3
|
- 1.9.2
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
|
-
|
6
|
+
|
7
7
|
gemfile:
|
8
8
|
- gemfiles/3.1.gemfile
|
9
9
|
- gemfiles/3.2.gemfile
|
10
10
|
- gemfiles/4.0.gemfile
|
11
|
-
|
11
|
+
- gemfiles/4.1.gemfile
|
12
|
+
|
12
13
|
matrix:
|
13
14
|
exclude:
|
14
15
|
- rvm: 1.8.7
|
15
|
-
gemfile: gemfiles/4.0.gemfile
|
16
|
+
gemfile: gemfiles/4.0.gemfile
|
17
|
+
- rvm: 1.8.7
|
18
|
+
gemfile: gemfiles/4.1.gemfile
|
19
|
+
- rvm: 1.9.2
|
20
|
+
gemfile: gemfiles/4.0.gemfile
|
16
21
|
- rvm: 1.9.2
|
17
|
-
gemfile: gemfiles/4.
|
22
|
+
gemfile: gemfiles/4.1.gemfile
|
data/Appraisals
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -8,7 +8,7 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
|
|
8
8
|
|
9
9
|
* Ruby 1.8.7, 1.9.3, 2.0.0
|
10
10
|
|
11
|
-
* Activerecord 3.1, 3.2, 4.0
|
11
|
+
* Activerecord 3.1, 3.2, 4.0, 4.1
|
12
12
|
|
13
13
|
* Rails 2.x/3.0 users, please check out the 'rails2.x-3.0' branch.
|
14
14
|
|
@@ -16,10 +16,10 @@ 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.6.
|
19
|
+
gem 'deep_cloneable', '~> 1.6.1'
|
20
20
|
|
21
21
|
== Example
|
22
|
-
|
22
|
+
|
23
23
|
=== Cloning one single association
|
24
24
|
pirate.dup :include => :mateys
|
25
25
|
|
@@ -34,10 +34,10 @@ This gem gives every ActiveRecord::Base object the possibility to do a deep clon
|
|
34
34
|
|
35
35
|
=== Cloning really deep with multiple associations and a dictionary
|
36
36
|
|
37
|
-
A dictionary ensures that models are not cloned multiple times when it is associated to nested models.
|
37
|
+
A dictionary ensures that models are not cloned multiple times when it is associated to nested models.
|
38
38
|
When using a dictionary, ensure recurring associations are cloned first:
|
39
39
|
|
40
|
-
pirate.dup :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :use_dictionary => true
|
40
|
+
pirate.dup :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :use_dictionary => true
|
41
41
|
|
42
42
|
If this is not an option for you, it is also possible to populate the dictionary manually in advance:
|
43
43
|
|
@@ -46,35 +46,35 @@ If this is not an option for you, it is also possible to populate the dictionary
|
|
46
46
|
pirate.dup :include => [:mateys, {:treasures => [:matey, :gold_pieces]}], :dictionary => dict
|
47
47
|
|
48
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 dups to avoid creating multiples of the same object where you have overlapping associations.
|
49
|
-
|
49
|
+
|
50
50
|
=== Cloning a model without an attribute
|
51
51
|
pirate.dup :except => :name
|
52
|
-
|
52
|
+
|
53
53
|
=== Cloning a model without multiple attributes
|
54
54
|
pirate.dup :except => [:name, :nick_name]
|
55
55
|
|
56
|
-
=== Cloning a model without an attribute or nested multiple attributes
|
56
|
+
=== Cloning a model without an attribute or nested multiple attributes
|
57
57
|
pirate.dup :include => :parrot, :except => [:name, { :parrot => [:name] }]
|
58
58
|
|
59
59
|
=== Cloning with a block
|
60
60
|
pirate.dup :include => :parrot do |original, kopy|
|
61
61
|
kopy.cloned_from_id = original.id if kopy.respond_to?(:cloned_from_id)
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
=== Cloning without validations
|
65
65
|
pirate.dup :include => {:treasures => :gold_pieces}, :validate => false
|
66
66
|
|
67
67
|
=== Cloning a model with only explicitly assigned attribute
|
68
68
|
pirate.dup :only => :name
|
69
|
-
|
69
|
+
|
70
70
|
=== Cloning a model with only multiple explicitly assigned attributes
|
71
|
-
pirate.dup :only => [:name, :nick_name]
|
71
|
+
pirate.dup :only => [:name, :nick_name]
|
72
72
|
|
73
|
-
=== Cloning a model with explicitly assigned attributes or nested multiple attributes
|
73
|
+
=== Cloning a model with explicitly assigned attributes or nested multiple attributes
|
74
74
|
pirate.dup :include => :parrot, :only => [:name, { :parrot => [:name] }]
|
75
75
|
|
76
76
|
== Note on Patches/Pull Requests
|
77
|
-
|
77
|
+
|
78
78
|
* Fork the project.
|
79
79
|
* Make your feature addition or bug fix.
|
80
80
|
* Add tests for it. This is important so I don't break it in a
|
@@ -85,4 +85,4 @@ When an object isn't found in the dictionary, it will be populated. By passing i
|
|
85
85
|
|
86
86
|
== Copyright
|
87
87
|
|
88
|
-
Copyright (c)
|
88
|
+
Copyright (c) 2014 Reinier de Lange. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.6.
|
1
|
+
1.6.1
|
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.6.
|
8
|
+
s.version = "1.6.1"
|
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 = "
|
12
|
+
s.date = "2014-04-18"
|
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 = [
|
@@ -33,6 +33,8 @@ Gem::Specification.new do |s|
|
|
33
33
|
"gemfiles/3.2.gemfile.lock",
|
34
34
|
"gemfiles/4.0.gemfile",
|
35
35
|
"gemfiles/4.0.gemfile.lock",
|
36
|
+
"gemfiles/4.1.gemfile",
|
37
|
+
"gemfiles/4.1.gemfile.lock",
|
36
38
|
"init.rb",
|
37
39
|
"lib/deep_cloneable.rb",
|
38
40
|
"test/database.yml",
|
data/gemfiles/3.1.gemfile
CHANGED
data/gemfiles/3.1.gemfile.lock
CHANGED
@@ -19,6 +19,7 @@ GEM
|
|
19
19
|
builder (3.0.4)
|
20
20
|
i18n (0.6.4)
|
21
21
|
json (1.8.0)
|
22
|
+
minitest (4.7.5)
|
22
23
|
multi_json (1.7.9)
|
23
24
|
rake (10.1.0)
|
24
25
|
rdoc (4.0.1)
|
@@ -33,5 +34,6 @@ DEPENDENCIES
|
|
33
34
|
activerecord (~> 3.1.0)
|
34
35
|
activesupport (>= 3.1.0)
|
35
36
|
appraisal
|
37
|
+
minitest
|
36
38
|
rdoc (>= 2.4.2)
|
37
39
|
sqlite3
|
data/gemfiles/3.2.gemfile
CHANGED
data/gemfiles/3.2.gemfile.lock
CHANGED
@@ -19,6 +19,7 @@ GEM
|
|
19
19
|
builder (3.0.4)
|
20
20
|
i18n (0.6.4)
|
21
21
|
json (1.8.0)
|
22
|
+
minitest (4.7.5)
|
22
23
|
multi_json (1.7.9)
|
23
24
|
rake (10.1.0)
|
24
25
|
rdoc (4.0.1)
|
@@ -33,5 +34,6 @@ DEPENDENCIES
|
|
33
34
|
activerecord (~> 3.2.0)
|
34
35
|
activesupport (>= 3.1.0)
|
35
36
|
appraisal
|
37
|
+
minitest
|
36
38
|
rdoc (>= 2.4.2)
|
37
39
|
sqlite3
|
data/gemfiles/4.0.gemfile
CHANGED
data/gemfiles/4.0.gemfile.lock
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "http://rubygems.org"
|
4
|
+
|
5
|
+
gem "minitest", :group=>:test
|
6
|
+
gem "activesupport", ">= 3.1.0", :group=>:test
|
7
|
+
gem "appraisal", :group=>:test
|
8
|
+
gem "sqlite3", :group=>:test
|
9
|
+
gem "rdoc", ">= 2.4.2", :group=>:test
|
10
|
+
gem "activerecord", "~> 4.1.0"
|
11
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (4.1.0)
|
5
|
+
activesupport (= 4.1.0)
|
6
|
+
builder (~> 3.1)
|
7
|
+
activerecord (4.1.0)
|
8
|
+
activemodel (= 4.1.0)
|
9
|
+
activesupport (= 4.1.0)
|
10
|
+
arel (~> 5.0.0)
|
11
|
+
activesupport (4.1.0)
|
12
|
+
i18n (~> 0.6, >= 0.6.9)
|
13
|
+
json (~> 1.7, >= 1.7.7)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
thread_safe (~> 0.1)
|
16
|
+
tzinfo (~> 1.1)
|
17
|
+
appraisal (1.0.0)
|
18
|
+
bundler
|
19
|
+
rake
|
20
|
+
thor (>= 0.14.0)
|
21
|
+
arel (5.0.1.20140414130214)
|
22
|
+
builder (3.2.2)
|
23
|
+
i18n (0.6.9)
|
24
|
+
json (1.8.1)
|
25
|
+
minitest (5.3.3)
|
26
|
+
rake (10.3.0)
|
27
|
+
rdoc (4.1.1)
|
28
|
+
json (~> 1.4)
|
29
|
+
sqlite3 (1.3.9)
|
30
|
+
thor (0.19.1)
|
31
|
+
thread_safe (0.3.3)
|
32
|
+
tzinfo (1.1.0)
|
33
|
+
thread_safe (~> 0.1)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
activerecord (~> 4.1.0)
|
40
|
+
activesupport (>= 3.1.0)
|
41
|
+
appraisal
|
42
|
+
minitest
|
43
|
+
rdoc (>= 2.4.2)
|
44
|
+
sqlite3
|
data/lib/deep_cloneable.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class ActiveRecord::Base
|
2
2
|
module DeepCloneable
|
3
|
-
|
3
|
+
|
4
4
|
if ActiveRecord::VERSION::MAJOR < 4
|
5
5
|
ActiveRecord::Base.class_eval do
|
6
6
|
protected :initialize_dup
|
@@ -79,7 +79,7 @@ class ActiveRecord::Base
|
|
79
79
|
end
|
80
80
|
|
81
81
|
cloned_object = send(
|
82
|
-
"dup_#{association_reflection.macro}_#{association_reflection.class.name.demodulize.underscore.gsub('_reflection', '')}",
|
82
|
+
"dup_#{association_reflection.macro}_#{association_reflection.class.name.demodulize.underscore.gsub('_reflection', '')}",
|
83
83
|
{ :reflection => association_reflection, :association => association, :copy => kopy, :dup_options => dup_options },
|
84
84
|
&block
|
85
85
|
)
|
@@ -90,17 +90,17 @@ class ActiveRecord::Base
|
|
90
90
|
|
91
91
|
return kopy
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
private
|
95
|
-
|
95
|
+
|
96
96
|
def dup_belongs_to_association options, &block
|
97
97
|
self.send(options[:association]) && self.send(options[:association]).dup(options[:dup_options], &block)
|
98
|
-
end
|
99
|
-
|
98
|
+
end
|
99
|
+
|
100
100
|
def dup_has_one_association options, &block
|
101
101
|
dup_belongs_to_association options, &block
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
def dup_has_many_association options, &block
|
105
105
|
primary_key_name = options[:reflection].foreign_key.to_s
|
106
106
|
|
@@ -113,32 +113,32 @@ class ActiveRecord::Base
|
|
113
113
|
tmp.send("#{primary_key_name}=", nil)
|
114
114
|
tmp.send("#{reverse_association_name.to_s}=", options[:copy]) if reverse_association_name
|
115
115
|
tmp
|
116
|
-
end
|
116
|
+
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def dup_has_many_through options, &block
|
120
120
|
dup_join_association(
|
121
|
-
options.merge(:macro => :has_many, :primary_key_name => options[:reflection].through_reflection.foreign_key.to_s),
|
121
|
+
options.merge(:macro => :has_many, :primary_key_name => options[:reflection].through_reflection.foreign_key.to_s),
|
122
122
|
&block)
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
def dup_has_and_belongs_to_many_association options, &block
|
126
126
|
dup_join_association(
|
127
|
-
options.merge(:macro => :has_and_belongs_to_many, :primary_key_name => options[:reflection].foreign_key.to_s),
|
127
|
+
options.merge(:macro => :has_and_belongs_to_many, :primary_key_name => options[:reflection].foreign_key.to_s),
|
128
128
|
&block)
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
def dup_join_association options, &block
|
132
132
|
reverse_association_name = options[:reflection].klass.reflect_on_all_associations.detect do |reflection|
|
133
133
|
(reflection.macro == options[:macro]) && (reflection.association_foreign_key.to_s == options[:primary_key_name])
|
134
134
|
end.try(:name)
|
135
135
|
|
136
136
|
self.send(options[:association]).collect do |obj|
|
137
|
-
obj.send(reverse_association_name).target << options[:copy]
|
137
|
+
obj.send(reverse_association_name).target << options[:copy] if reverse_association_name
|
138
138
|
obj
|
139
|
-
end
|
139
|
+
end
|
140
140
|
end
|
141
|
-
|
141
|
+
|
142
142
|
class AssociationNotFoundException < StandardError; end
|
143
143
|
end
|
144
144
|
|
data/test/models.rb
CHANGED
@@ -53,6 +53,10 @@ class Car < ActiveRecord::Base
|
|
53
53
|
has_and_belongs_to_many :people
|
54
54
|
end
|
55
55
|
|
56
|
+
class Coin < ActiveRecord::Base
|
57
|
+
has_and_belongs_to_many :people
|
58
|
+
end
|
59
|
+
|
56
60
|
class ChildWithValidation < ActiveRecord::Base
|
57
61
|
belongs_to :parent, :class_name => 'ParentWithValidation'
|
58
62
|
validates :name, :presence => true
|
@@ -64,14 +68,14 @@ class ParentWithValidation < ActiveRecord::Base
|
|
64
68
|
end
|
65
69
|
|
66
70
|
class Part < ActiveRecord::Base
|
67
|
-
# belongs_to :parent_part, :class_name => 'Part'
|
71
|
+
# belongs_to :parent_part, :class_name => 'Part'
|
68
72
|
has_many :child_parts, :class_name => 'Part', :foreign_key => 'parent_part_id'
|
69
73
|
end
|
70
74
|
|
71
75
|
class Student < ActiveRecord::Base
|
72
76
|
has_many :student_assignments, :dependent => :destroy
|
73
77
|
has_many :subjects, :through => :student_assignments
|
74
|
-
end
|
78
|
+
end
|
75
79
|
|
76
80
|
class Subject < ActiveRecord::Base
|
77
81
|
has_many :student_assignments, :dependent => :destroy
|
@@ -80,5 +84,5 @@ end
|
|
80
84
|
|
81
85
|
class StudentAssignment < ActiveRecord::Base
|
82
86
|
belongs_to :subject
|
83
|
-
belongs_to :student
|
87
|
+
belongs_to :student
|
84
88
|
end
|
data/test/schema.rb
CHANGED
@@ -54,6 +54,10 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
54
54
|
t.column :name, :string
|
55
55
|
end
|
56
56
|
|
57
|
+
create_table :coins, :force => true do |t|
|
58
|
+
t.column :value, :integer
|
59
|
+
end
|
60
|
+
|
57
61
|
create_table :people, :force => true do |t|
|
58
62
|
t.column :name, :string
|
59
63
|
end
|
@@ -63,6 +67,11 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
63
67
|
t.column :person_id, :integer
|
64
68
|
end
|
65
69
|
|
70
|
+
create_table :coins_people, :id => false, :force => true do |t|
|
71
|
+
t.column :coin_id, :integer
|
72
|
+
t.column :person_id, :integer
|
73
|
+
end
|
74
|
+
|
66
75
|
create_table :parent_with_validations, :force => true do |t|
|
67
76
|
t.column :name, :string
|
68
77
|
end
|
@@ -76,10 +85,10 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
76
85
|
t.column :name, :string
|
77
86
|
t.column :parent_part_id, :integer
|
78
87
|
end
|
79
|
-
|
88
|
+
|
80
89
|
create_table :students, :force => true do |t|
|
81
90
|
t.column :name, :string
|
82
|
-
end
|
91
|
+
end
|
83
92
|
|
84
93
|
create_table :subjects, :force => true do |t|
|
85
94
|
t.column :name, :string
|
@@ -87,6 +96,6 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
87
96
|
|
88
97
|
create_table :student_assignments, :force => true do |t|
|
89
98
|
t.column :student_id, :integer
|
90
|
-
t.column :subject_id, :integer
|
91
|
-
end
|
99
|
+
t.column :subject_id, :integer
|
100
|
+
end
|
92
101
|
end
|
data/test/test_deep_cloneable.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper'
|
2
2
|
|
3
|
-
class TestDeepCloneable <
|
3
|
+
class TestDeepCloneable < MiniTest::Unit::TestCase
|
4
4
|
|
5
5
|
def setup
|
6
6
|
@jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
|
@@ -62,8 +62,8 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
62
62
|
dup = @jack.dup(:include => :ship)
|
63
63
|
assert dup.new_record?
|
64
64
|
assert dup.save
|
65
|
-
|
66
|
-
|
65
|
+
refute_nil dup.ship
|
66
|
+
refute_equal @jack.ship, dup.ship
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_single_include_has_many_polymorphic_association
|
@@ -120,16 +120,16 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
120
120
|
dup = @jack.dup(:include => :parrot)
|
121
121
|
assert dup.new_record?
|
122
122
|
assert dup.save
|
123
|
-
|
123
|
+
refute_equal dup.parrot, @jack.parrot
|
124
124
|
end
|
125
125
|
|
126
126
|
def test_should_pass_nested_exceptions
|
127
127
|
dup = @jack.dup(:include => :parrot, :except => [:name, { :parrot => [:name] }])
|
128
128
|
assert dup.new_record?
|
129
129
|
assert dup.save
|
130
|
-
|
130
|
+
refute_equal dup.parrot, @jack.parrot
|
131
131
|
assert_equal dup.parrot.age, @jack.parrot.age
|
132
|
-
|
132
|
+
refute_nil @jack.parrot.name
|
133
133
|
assert_nil dup.parrot.name
|
134
134
|
end
|
135
135
|
|
@@ -137,7 +137,7 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
137
137
|
dup = @jack.dup(:include => :parrot, :only => [:name, { :parrot => [:name] }])
|
138
138
|
assert dup.new_record?
|
139
139
|
assert dup.save
|
140
|
-
|
140
|
+
refute_equal dup.parrot, @jack.parrot
|
141
141
|
assert_equal dup.parrot.name, @jack.parrot.name
|
142
142
|
assert_nil dup.parrot.age
|
143
143
|
end
|
@@ -230,12 +230,23 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
230
230
|
assert_equal @person1.cars, dup_person.cars
|
231
231
|
assert_equal 2, dup_person.cars.count
|
232
232
|
end
|
233
|
-
|
233
|
+
|
234
|
+
def test_should_dup_habtm_associations_with_missing_reverse_association
|
235
|
+
@coin = Coin.create :value => 1
|
236
|
+
@person = Person.create :name => "Bill"
|
237
|
+
@coin.people << @person
|
238
|
+
|
239
|
+
dup = @coin.dup :include => :people
|
240
|
+
assert dup.new_record?
|
241
|
+
assert_equal [@person], @coin.people
|
242
|
+
assert dup.save
|
243
|
+
end
|
244
|
+
|
234
245
|
def test_should_dup_joined_association
|
235
246
|
subject1 = Subject.create(:name => 'subject 1')
|
236
247
|
subject2 = Subject.create(:name => 'subject 2')
|
237
248
|
student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
|
238
|
-
|
249
|
+
|
239
250
|
dup = student.dup :include => { :student_assignments => :subject }
|
240
251
|
dup.save # Subjects will have been set after save
|
241
252
|
assert_equal 2, dup.subjects.size
|
@@ -307,12 +318,12 @@ class TestDeepCloneable < Test::Unit::TestCase
|
|
307
318
|
assert dup_part.save
|
308
319
|
assert_equal 2, dup_part.child_parts.size
|
309
320
|
end
|
310
|
-
|
321
|
+
|
311
322
|
def test_should_include_has_many_through_associations
|
312
323
|
subject1 = Subject.create(:name => 'subject 1')
|
313
324
|
subject2 = Subject.create(:name => 'subject 2')
|
314
325
|
student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
|
315
|
-
|
326
|
+
|
316
327
|
dup = student.dup :include => :subjects
|
317
328
|
assert_equal 2, dup.subjects.size
|
318
329
|
assert_equal [[student, dup],[student, dup]], dup.subjects.map{|subject| subject.students }
|
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'yaml'
|
3
|
+
require 'minitest/autorun'
|
3
4
|
#require 'pp'
|
4
5
|
#require 'debugger'
|
5
6
|
|
@@ -7,11 +8,16 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
7
8
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
9
|
|
9
10
|
require 'active_record'
|
10
|
-
require 'active_support/buffered_logger'
|
11
11
|
|
12
12
|
def load_schema
|
13
13
|
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
14
|
-
|
14
|
+
|
15
|
+
if defined?(ActiveSupport::BufferedLogger)
|
16
|
+
ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/debug.log")
|
17
|
+
else
|
18
|
+
ActiveRecord::Base.logger = ActiveSupport::Logger.new(File.dirname(__FILE__) + "/debug.log")
|
19
|
+
end
|
20
|
+
|
15
21
|
db_adapter = ENV['DB']
|
16
22
|
# no db passed, try one of these fine config-free DBs before bombing.
|
17
23
|
db_adapter ||= begin
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deep_cloneable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.1
|
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:
|
11
|
+
date: 2014-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -49,6 +49,8 @@ files:
|
|
49
49
|
- gemfiles/3.2.gemfile.lock
|
50
50
|
- gemfiles/4.0.gemfile
|
51
51
|
- gemfiles/4.0.gemfile.lock
|
52
|
+
- gemfiles/4.1.gemfile
|
53
|
+
- gemfiles/4.1.gemfile.lock
|
52
54
|
- init.rb
|
53
55
|
- lib/deep_cloneable.rb
|
54
56
|
- test/database.yml
|