deep_cloneable 2.0.2 → 3.1.0

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/test/database.yml DELETED
@@ -1,6 +0,0 @@
1
- sqlite:
2
- adapter: sqlite
3
- database: ":memory:"
4
- sqlite3:
5
- adapter: sqlite3
6
- database: ":memory:"
data/test/models.rb DELETED
@@ -1,88 +0,0 @@
1
- module Animal
2
- class Human < ActiveRecord::Base
3
- has_many :pigs
4
-
5
- has_many :ownerships
6
- has_many :chickens, :through => :ownerships
7
- end
8
- class Pig < ActiveRecord::Base
9
- belongs_to :human
10
- end
11
-
12
- class Chicken < ActiveRecord::Base
13
- has_many :ownerships
14
- has_many :humans, :through => :ownerships
15
- end
16
-
17
- class Ownership < ActiveRecord::Base
18
- belongs_to :human
19
- belongs_to :chicken
20
-
21
- validates_uniqueness_of :chicken_id, :scope => :human_id
22
- end
23
-
24
- end
25
-
26
- class GoldPiece < ActiveRecord::Base; belongs_to :treasure end
27
- class Matey < ActiveRecord::Base; belongs_to :pirate end
28
- class Parrot < ActiveRecord::Base; belongs_to :pirate; attr_accessor :cloned_from_id end
29
- class BattleShip < ActiveRecord::Base; has_many :pirates, :as => :ship end
30
-
31
- class Pirate < ActiveRecord::Base
32
- belongs_to :ship, :polymorphic => true
33
-
34
- has_many :mateys
35
- has_many :treasures, :foreign_key => 'owner'
36
- has_many :gold_pieces, :through => :treasures
37
- has_one :parrot
38
-
39
- attr_accessor :cloned_from_id
40
- end
41
-
42
- class Treasure < ActiveRecord::Base
43
- belongs_to :pirate, :foreign_key => :owner
44
- belongs_to :matey
45
- has_many :gold_pieces
46
- end
47
-
48
- class Person < ActiveRecord::Base
49
- has_and_belongs_to_many :cars
50
- end
51
-
52
- class Car < ActiveRecord::Base
53
- has_and_belongs_to_many :people
54
- end
55
-
56
- class Coin < ActiveRecord::Base
57
- has_and_belongs_to_many :people
58
- end
59
-
60
- class ChildWithValidation < ActiveRecord::Base
61
- belongs_to :parent, :class_name => 'ParentWithValidation'
62
- validates :name, :presence => true
63
- end
64
-
65
- class ParentWithValidation < ActiveRecord::Base
66
- has_many :children, :class_name => 'ChildWithValidation'
67
- validates :name, :presence => true
68
- end
69
-
70
- class Part < ActiveRecord::Base
71
- # belongs_to :parent_part, :class_name => 'Part'
72
- has_many :child_parts, :class_name => 'Part', :foreign_key => 'parent_part_id'
73
- end
74
-
75
- class Student < ActiveRecord::Base
76
- has_many :student_assignments, :dependent => :destroy
77
- has_many :subjects, :through => :student_assignments
78
- end
79
-
80
- class Subject < ActiveRecord::Base
81
- has_many :student_assignments, :dependent => :destroy
82
- has_many :students, :through => :student_assignments
83
- end
84
-
85
- class StudentAssignment < ActiveRecord::Base
86
- belongs_to :subject
87
- belongs_to :student
88
- end
data/test/schema.rb DELETED
@@ -1,101 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 1) do
2
- create_table :pirates, :force => true do |t|
3
- t.column :name, :string
4
- t.column :nick_name, :string, :default => 'no nickname'
5
- t.column :age, :string
6
- t.column :ship_id, :integer
7
- t.column :ship_type, :string
8
- end
9
-
10
- create_table :parrots, :force => true do |t|
11
- t.column :name, :string
12
- t.column :age, :integer
13
- t.column :pirate_id, :integer
14
- end
15
-
16
- create_table :mateys, :force => true do |t|
17
- t.column :name, :string
18
- t.column :pirate_id, :integer
19
- end
20
-
21
- create_table :treasures, :force => true do |t|
22
- t.column :found_at, :string
23
- t.column :owner, :integer
24
- t.column :matey_id, :integer
25
- end
26
-
27
- create_table :gold_pieces, :force => true do |t|
28
- t.column :treasure_id, :integer
29
- end
30
-
31
- create_table :battle_ships, :force => true do |t|
32
- t.column :name, :string
33
- end
34
-
35
- create_table :pigs, :force => true do |t|
36
- t.column :name, :string
37
- t.column :human_id, :integer
38
- end
39
-
40
- create_table :humen, :force => true do |t|
41
- t.column :name, :string
42
- end
43
-
44
- create_table :chickens, :force => true do |t|
45
- t.column :name, :string
46
- end
47
-
48
- create_table :ownerships, :force => true do |t|
49
- t.column :human_id, :integer
50
- t.column :chicken_id, :integer
51
- end
52
-
53
- create_table :cars, :force => true do |t|
54
- t.column :name, :string
55
- end
56
-
57
- create_table :coins, :force => true do |t|
58
- t.column :value, :integer
59
- end
60
-
61
- create_table :people, :force => true do |t|
62
- t.column :name, :string
63
- end
64
-
65
- create_table :cars_people, :id => false, :force => true do |t|
66
- t.column :car_id, :integer
67
- t.column :person_id, :integer
68
- end
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
-
75
- create_table :parent_with_validations, :force => true do |t|
76
- t.column :name, :string
77
- end
78
-
79
- create_table :child_with_validations, :force => true do |t|
80
- t.column :name, :string
81
- t.column :parent_with_validation_id, :integer
82
- end
83
-
84
- create_table :parts, :force => true do |t|
85
- t.column :name, :string
86
- t.column :parent_part_id, :integer
87
- end
88
-
89
- create_table :students, :force => true do |t|
90
- t.column :name, :string
91
- end
92
-
93
- create_table :subjects, :force => true do |t|
94
- t.column :name, :string
95
- end
96
-
97
- create_table :student_assignments, :force => true do |t|
98
- t.column :student_id, :integer
99
- t.column :subject_id, :integer
100
- end
101
- end
@@ -1,342 +0,0 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- class TestDeepCloneable < MiniTest::Unit::TestCase
4
-
5
- def setup
6
- @jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
7
- @polly = Parrot.create(:name => 'Polly', :age => 2, :pirate => @jack)
8
- @john = Matey.create(:name => 'John', :pirate => @jack)
9
- @treasure = Treasure.create(:found_at => 'Isla del Muerte', :pirate => @jack, :matey => @john)
10
- @gold_piece = GoldPiece.create(:treasure => @treasure)
11
- @ship = BattleShip.create(:name => 'Black Pearl', :pirates => [@jack])
12
- end
13
-
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
- end
53
-
54
- def test_single_include_association
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
- end
60
-
61
- def test_single_include_belongs_to_polymorphic_association
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
- end
68
-
69
- def test_single_include_has_many_polymorphic_association
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
- end
75
-
76
- def test_multiple_include_association
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
- end
83
-
84
- def test_deep_include_association
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
- end
91
-
92
- def test_include_association_assignments
93
- deep_clone = @jack.deep_clone(:include => :treasures)
94
- assert deep_clone.new_record?
95
-
96
- deep_clone.treasures.each do |treasure|
97
- assert_equal deep_clone, treasure.pirate
98
- end
99
- end
100
-
101
- def test_multiple_and_deep_include_association
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
- end
109
-
110
- def test_multiple_and_deep_include_association_with_array
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
- end
118
-
119
- def test_with_belongs_to_relation
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
- end
125
-
126
- def test_should_pass_nested_exceptions
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
- refute_nil @jack.parrot.name
133
- assert_nil deep_clone.parrot.name
134
- end
135
-
136
- def test_should_pass_nested_onlinesses
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
- end
144
-
145
- def test_should_not_double_deep_clone_when_using_dictionary
146
- current_matey_count = Matey.count
147
- deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
148
- assert deep_clone.new_record?
149
- deep_clone.save!
150
-
151
- assert_equal current_matey_count + 1, Matey.count
152
- end
153
-
154
- def test_should_not_double_deep_clone_when_using_manual_dictionary
155
- current_matey_count = Matey.count
156
-
157
- dict = { :mateys => {} }
158
- @jack.mateys.each{|m| dict[:mateys][m] = m.deep_clone }
159
-
160
- deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
161
- assert deep_clone.new_record?
162
- deep_clone.save!
163
-
164
- assert_equal current_matey_count + 1, Matey.count
165
- end
166
-
167
- def test_should_support_ar_class_under_module
168
- @human = Animal::Human.create :name => "Michael"
169
- @pig = Animal::Pig.create :human => @human, :name => 'big pig'
170
-
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
-
176
- @human2 = Animal::Human.create :name => "John"
177
- @pig2 = @human2.pigs.create :name => 'small pig'
178
-
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
- end
184
-
185
- def test_should_deep_clone_many_to_many_associations
186
- @human = Animal::Human.create :name => "Michael"
187
- @human2 = Animal::Human.create :name => "Jack"
188
- @chicken1 = Animal::Chicken.create :name => 'Chick1'
189
- @chicken2 = Animal::Chicken.create :name => 'Chick2'
190
- @human.chickens << [@chicken1, @chicken2]
191
- @human2.chickens << [@chicken1, @chicken2]
192
-
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
- end
198
-
199
- def test_should_deep_clone_with_block
200
- deep_clone = @jack.deep_clone(:include => :parrot) do |original, kopy|
201
- kopy.cloned_from_id = original.id
202
- end
203
-
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
- end
209
-
210
- def test_should_deep_clone_habtm_associations
211
- @person1 = Person.create :name => "Bill"
212
- @person2 = Person.create :name => "Ted"
213
- @car1 = Car.create :name => 'Mustang'
214
- @car2 = Car.create :name => 'Camaro'
215
- @person1.cars << [@car1, @car2]
216
- @person2.cars << [@car1, @car2]
217
-
218
- deep_clone_person = @person1.deep_clone :include => :cars
219
-
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
-
224
- assert deep_clone_person.save
225
-
226
- # did NOT deep_clone the Car instances
227
- assert_equal 2, Car.all.count
228
-
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
- end
233
-
234
- def test_should_deep_clone_habtm_associations_with_missing_reverse_association
235
- @coin = Coin.create :value => 1
236
- @person = Person.create :name => "Bill"
237
- @coin.people << @person
238
-
239
- deep_clone = @coin.deep_clone :include => :people
240
- assert deep_clone.new_record?
241
- assert_equal [@person], @coin.people
242
- assert deep_clone.save
243
- end
244
-
245
- def test_should_deep_clone_joined_association
246
- subject1 = Subject.create(:name => 'subject 1')
247
- subject2 = Subject.create(:name => 'subject 2')
248
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
249
-
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
- end
255
-
256
- def test_parent_validations_run_on_save_after_clone
257
- child = ChildWithValidation.create :name => 'Jimmy'
258
- parent = ParentWithValidation.new :children => [child]
259
- parent.save :validate => false
260
-
261
- deep_clone_parent = parent.deep_clone :include => :children
262
-
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
- end
269
-
270
- def test_parent_validations_dont_run_on_save_after_clone
271
- child = ChildWithValidation.create :name => 'Jimmy'
272
- parent = ParentWithValidation.new :children => [child]
273
- parent.save :validate => false
274
-
275
- deep_clone_parent = parent.deep_clone :include => :children, :validate => false
276
-
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
- end
283
-
284
- def test_child_validations_run_on_save_after_clone
285
- child = ChildWithValidation.new
286
- child.save :validate => false
287
- parent = ParentWithValidation.create :name => 'John', :children => [child]
288
-
289
- deep_clone_parent = parent.deep_clone :include => :children
290
-
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
- end
297
-
298
- def test_child_validations_run_on_save_after_clone_without_validation
299
- child = ChildWithValidation.new
300
- child.save :validate => false
301
- parent = ParentWithValidation.create :name => 'John', :children => [child]
302
-
303
- deep_clone_parent = parent.deep_clone :include => :children, :validate => false
304
-
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
- end
311
-
312
- def test_self_join_has_many
313
- parent_part = Part.create(:name => 'Parent')
314
- child1 = Part.create(:name => 'Child 1', :parent_part_id => parent_part.id)
315
- child2 = Part.create(:name => 'Child 2', :parent_part_id => parent_part.id)
316
-
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
- end
321
-
322
- def test_should_include_has_many_through_associations
323
- subject1 = Subject.create(:name => 'subject 1')
324
- subject2 = Subject.create(:name => 'subject 2')
325
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
326
-
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
- end