deep_cloneable 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,509 +0,0 @@
1
- require 'test_helper'
2
-
3
- class TestDeepCloneable < MiniTest::Unit::TestCase
4
- def setup
5
- @jack = Pirate.create(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
6
- @polly = Parrot.create(:name => 'Polly', :age => 2, :pirate => @jack)
7
- @john = Matey.create(:name => 'John', :pirate => @jack)
8
- @treasure = Treasure.create(:found_at => 'Isla del Muerte', :pirate => @jack, :matey => @john)
9
- @gold_piece = GoldPiece.create(:treasure => @treasure)
10
- @ship = BattleShip.create(:name => 'Black Pearl', :pirates => [@jack])
11
- end
12
-
13
- def test_single_deep_clone_exception
14
- deep_clone = @jack.deep_clone(:except => :name)
15
- assert deep_clone.new_record?
16
- assert deep_clone.save
17
- assert_equal @jack.name, @jack.deep_clone.name
18
- assert_nil deep_clone.name
19
- assert_equal @jack.nick_name, deep_clone.nick_name
20
- end
21
-
22
- def test_multiple_deep_clone_exception
23
- deep_clone = @jack.deep_clone(:except => [:name, :nick_name])
24
- assert deep_clone.new_record?
25
- assert deep_clone.save
26
- assert_nil deep_clone.name
27
- assert_equal 'no nickname', deep_clone.nick_name
28
- assert_equal @jack.age, deep_clone.age
29
- end
30
-
31
- def test_single_deep_clone_onliness
32
- deep_clone = @jack.deep_clone(:only => :name)
33
- assert deep_clone.new_record?
34
- assert deep_clone.piastres, []
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.piastres, []
47
- assert deep_clone.save
48
- assert_equal @jack.name, deep_clone.name
49
- assert_equal @jack.nick_name, deep_clone.nick_name
50
- assert_nil deep_clone.age
51
- assert_nil deep_clone.ship_id
52
- assert_nil deep_clone.ship_type
53
- end
54
-
55
- def test_single_include_association
56
- deep_clone = @jack.deep_clone(:include => :mateys)
57
- assert deep_clone.new_record?
58
- assert deep_clone.save
59
- assert_equal 1, deep_clone.mateys.size
60
- end
61
-
62
- def test_single_include_belongs_to_polymorphic_association
63
- deep_clone = @jack.deep_clone(:include => :ship)
64
- assert deep_clone.new_record?
65
- assert deep_clone.save
66
- refute_nil deep_clone.ship
67
- refute_equal @jack.ship, deep_clone.ship
68
- end
69
-
70
- def test_single_include_has_many_polymorphic_association
71
- deep_clone = @ship.deep_clone(:include => :pirates)
72
- assert deep_clone.new_record?
73
- assert deep_clone.save
74
- assert deep_clone.pirates.any?
75
- end
76
-
77
- def test_multiple_include_association
78
- deep_clone = @jack.deep_clone(:include => [:mateys, :treasures])
79
- assert deep_clone.new_record?
80
- assert deep_clone.save
81
- assert_equal 1, deep_clone.mateys.size
82
- assert_equal 1, deep_clone.treasures.size
83
- end
84
-
85
- def test_deep_include_association
86
- deep_clone = @jack.deep_clone(:include => { :treasures => :gold_pieces })
87
- assert deep_clone.new_record?
88
- assert deep_clone.save
89
- assert_equal 1, deep_clone.treasures.size
90
- assert_equal 1, deep_clone.gold_pieces.size
91
- end
92
-
93
- def test_include_association_assignments
94
- deep_clone = @jack.deep_clone(:include => :treasures)
95
- assert deep_clone.new_record?
96
-
97
- deep_clone.treasures.each do |treasure|
98
- assert_equal deep_clone, treasure.pirate
99
- end
100
- end
101
-
102
- def test_include_association_assignments_with_inverse_of
103
- @jack.pirate_cages.build
104
- deep_clone = @jack.deep_clone(:include => :pirate_cages)
105
- assert deep_clone.new_record?
106
- deep_clone.pirate_cages.each do |cage|
107
- assert_equal deep_clone, cage.pirate
108
- end
109
- end
110
-
111
- def test_multiple_and_deep_include_association
112
- deep_clone = @jack.deep_clone(:include => { :treasures => :gold_pieces, :mateys => {} })
113
- assert deep_clone.new_record?
114
- assert deep_clone.save
115
- assert_equal 1, deep_clone.treasures.size
116
- assert_equal 1, deep_clone.gold_pieces.size
117
- assert_equal 1, deep_clone.mateys.size
118
- end
119
-
120
- def test_multiple_and_deep_include_association_with_array
121
- deep_clone = @jack.deep_clone(:include => [{ :treasures => :gold_pieces }, :mateys])
122
- assert deep_clone.new_record?
123
- assert deep_clone.save
124
- assert_equal 1, deep_clone.treasures.size
125
- assert_equal 1, deep_clone.gold_pieces.size
126
- assert_equal 1, deep_clone.mateys.size
127
- end
128
-
129
- def test_multiple_and_deep_include_association_with_array_and_multikey_hash
130
- deep_clone = @jack.deep_clone(:include => [:parrot, { :treasures => :gold_pieces, :mateys => {} }])
131
- assert deep_clone.new_record?
132
- assert deep_clone.save
133
- assert_equal 1, deep_clone.treasures.size
134
- assert_equal 1, deep_clone.gold_pieces.size
135
- assert_equal 1, deep_clone.mateys.size
136
- end
137
-
138
- def test_with_belongs_to_relation
139
- deep_clone = @jack.deep_clone(:include => :parrot)
140
- assert deep_clone.new_record?
141
- assert deep_clone.save
142
- refute_equal deep_clone.parrot, @jack.parrot
143
- end
144
-
145
- def test_should_pass_nested_exceptions
146
- deep_clone = @jack.deep_clone(:include => :parrot, :except => [:name, { :parrot => [:name] }])
147
- assert deep_clone.new_record?
148
- assert deep_clone.save
149
- refute_equal deep_clone.parrot, @jack.parrot
150
- assert_equal deep_clone.parrot.age, @jack.parrot.age
151
- refute_nil @jack.parrot.name
152
- assert_nil deep_clone.parrot.name
153
- end
154
-
155
- def test_should_pass_nested_exception_with_hash_value
156
- deep_clone = @jack.deep_clone(:include => :parrot, :except => { :parrot => [:name] })
157
- assert deep_clone.new_record?
158
- assert deep_clone.save
159
- refute_equal deep_clone.parrot, @jack.parrot
160
- assert_equal deep_clone.parrot.age, @jack.parrot.age
161
- refute_nil @jack.parrot.name
162
- assert_nil deep_clone.parrot.name
163
- end
164
-
165
- def test_should_pass_nested_onlinesses
166
- deep_clone = @jack.deep_clone(:include => :parrot, :only => [:name, { :parrot => [:name] }])
167
- assert deep_clone.new_record?
168
- assert deep_clone.piastres, []
169
- assert deep_clone.save
170
- refute_equal deep_clone.parrot, @jack.parrot
171
- assert_equal deep_clone.parrot.name, @jack.parrot.name
172
- assert_nil deep_clone.parrot.age
173
- end
174
-
175
- def test_should_pass_nested_onliness_with_hash_value
176
- deep_clone = @jack.deep_clone(:include => :parrot, :only => { :parrot => [:name] })
177
- assert deep_clone.new_record?
178
- assert deep_clone.piastres, []
179
- assert deep_clone.save
180
- refute_equal deep_clone.parrot, @jack.parrot
181
- assert_equal deep_clone.parrot.name, @jack.parrot.name
182
- assert_nil deep_clone.parrot.age
183
- end
184
-
185
- def test_should_not_double_deep_clone_when_using_dictionary
186
- current_matey_count = Matey.count
187
- deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :use_dictionary => true)
188
- assert deep_clone.new_record?
189
- deep_clone.save!
190
-
191
- assert_equal current_matey_count + 1, Matey.count
192
- end
193
-
194
- def test_should_not_double_deep_clone_when_using_manual_dictionary
195
- current_matey_count = Matey.count
196
-
197
- dict = { :mateys => {} }
198
- @jack.mateys.each { |m| dict[:mateys][m] = m.deep_clone }
199
-
200
- deep_clone = @jack.deep_clone(:include => [:mateys, { :treasures => :matey }], :dictionary => dict)
201
- assert deep_clone.new_record?
202
- deep_clone.save!
203
-
204
- assert_equal current_matey_count + 1, Matey.count
205
- end
206
-
207
- def test_should_support_ar_class_under_module
208
- @human = Animal::Human.create :name => 'Michael'
209
- @pig = Animal::Pig.create :human => @human, :name => 'big pig'
210
-
211
- deep_clone_human = @human.deep_clone(:include => [:pigs])
212
- assert deep_clone_human.new_record?
213
- assert deep_clone_human.save
214
- assert_equal 1, deep_clone_human.pigs.count
215
-
216
- @human2 = Animal::Human.create :name => 'John'
217
- @pig2 = @human2.pigs.create :name => 'small pig'
218
-
219
- deep_clone_human2 = @human.deep_clone(:include => [:pigs])
220
- assert deep_clone_human2.new_record?
221
- assert deep_clone_human2.save
222
- assert_equal 1, deep_clone_human2.pigs.count
223
- end
224
-
225
- def test_should_deep_clone_many_to_many_associations
226
- @human = Animal::Human.create :name => 'Michael'
227
- @human2 = Animal::Human.create :name => 'Jack'
228
- @chicken1 = Animal::Chicken.create :name => 'Chick1'
229
- @chicken2 = Animal::Chicken.create :name => 'Chick2'
230
- @human.chickens << [@chicken1, @chicken2]
231
- @human2.chickens << [@chicken1, @chicken2]
232
-
233
- deep_clone_human = @human.deep_clone(:include => :ownerships)
234
- assert deep_clone_human.new_record?
235
- assert deep_clone_human.save
236
- assert_equal 2, deep_clone_human.chickens.count
237
- end
238
-
239
- def test_should_skip_missing_associations
240
- @earth = Animal::Planet.create :name => 'Earth'
241
- @human = Animal::Human.create :name => 'Michael'
242
- @chicken = Animal::Chicken.create :name => 'Chick', :humans => [@human], :planet => @earth
243
- @dove = Animal::Dove.create :name => 'Dovey', :planet => @earth
244
-
245
- assert_raises ::DeepCloneable::AssociationNotFoundException do
246
- @earth.deep_clone(:include => { :birds => :ownerships })
247
- end
248
-
249
- deep_clone_earth = @earth.deep_clone(:include => { :birds => :ownerships }, :skip_missing_associations => true)
250
- assert_equal 2, deep_clone_earth.birds.size
251
- assert deep_clone_earth.birds.detect { |bird| bird.is_a?(Animal::Chicken) }.ownerships.any?
252
- end
253
-
254
- def test_should_deep_clone_with_block
255
- deep_clone = @jack.deep_clone(:include => :parrot) do |original, kopy|
256
- kopy.cloned_from_id = original.id
257
- end
258
-
259
- assert deep_clone.new_record?
260
- assert deep_clone.save
261
- assert_equal @jack.id, deep_clone.cloned_from_id
262
- assert_equal @jack.parrot.id, deep_clone.parrot.cloned_from_id
263
- end
264
-
265
- def test_should_deep_clone_habtm_associations
266
- @person1 = Person.create :name => 'Bill'
267
- @person2 = Person.create :name => 'Ted'
268
- @car1 = Car.create :name => 'Mustang'
269
- @car2 = Car.create :name => 'Camaro'
270
- @person1.cars << [@car1, @car2]
271
- @person2.cars << [@car1, @car2]
272
-
273
- deep_clone_person = @person1.deep_clone :include => :cars
274
-
275
- assert deep_clone_person.new_record?
276
- assert_equal [@person1, @person2, deep_clone_person], @car1.people
277
- assert_equal [@person1, @person2, deep_clone_person], @car2.people
278
-
279
- assert deep_clone_person.save
280
-
281
- # did NOT deep_clone the Car instances
282
- assert_equal 2, Car.all.count
283
-
284
- # did deep_clone the correct join table rows
285
- assert_equal @person1.cars, deep_clone_person.cars
286
- assert_equal 2, deep_clone_person.cars.count
287
- end
288
-
289
- def test_should_deep_clone_habtm_associations_with_missing_reverse_association
290
- @coin = Coin.create :value => 1
291
- @person = Person.create :name => 'Bill'
292
- @coin.people << @person
293
-
294
- deep_clone = @coin.deep_clone :include => :people
295
- assert deep_clone.new_record?
296
- assert_equal [@person], @coin.people
297
- assert deep_clone.save
298
- end
299
-
300
- def test_should_deep_clone_joined_association
301
- subject1 = Subject.create(:name => 'subject 1')
302
- subject2 = Subject.create(:name => 'subject 2')
303
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
304
-
305
- deep_clone = student.deep_clone :include => { :student_assignments => :subject }
306
- deep_clone.save # Subjects will have been set after save
307
- assert_equal 2, deep_clone.subjects.size
308
- [subject1, subject2].each { |subject| assert !deep_clone.subjects.include?(subject) }
309
- end
310
-
311
- def test_parent_validations_run_on_save_after_clone
312
- child = ChildWithValidation.create :name => 'Jimmy'
313
- parent = ParentWithValidation.new :children => [child]
314
- parent.save :validate => false
315
-
316
- deep_clone_parent = parent.deep_clone :include => :children
317
-
318
- assert !deep_clone_parent.save
319
- assert deep_clone_parent.new_record?
320
- assert !deep_clone_parent.valid?
321
- assert deep_clone_parent.children.first.valid?
322
- assert_equal deep_clone_parent.errors.messages, :name => ["can't be blank"]
323
- end
324
-
325
- def test_parent_validations_dont_run_on_save_after_clone
326
- child = ChildWithValidation.create :name => 'Jimmy'
327
- parent = ParentWithValidation.new :children => [child]
328
- parent.save :validate => false
329
-
330
- deep_clone_parent = parent.deep_clone :include => :children, :validate => false
331
-
332
- assert deep_clone_parent.save
333
- assert !deep_clone_parent.new_record?
334
- assert !deep_clone_parent.valid?
335
- assert deep_clone_parent.children.first.valid?
336
- assert_equal deep_clone_parent.errors.messages, :name => ["can't be blank"]
337
- end
338
-
339
- def test_child_validations_run_on_save_after_clone
340
- child = ChildWithValidation.new
341
- child.save :validate => false
342
- parent = ParentWithValidation.create :name => 'John', :children => [child]
343
-
344
- deep_clone_parent = parent.deep_clone :include => :children
345
-
346
- assert !deep_clone_parent.save
347
- assert deep_clone_parent.new_record?
348
- assert !deep_clone_parent.valid?
349
- assert !deep_clone_parent.children.first.valid?
350
- assert_equal deep_clone_parent.errors.messages, :children => ['is invalid']
351
- end
352
-
353
- def test_child_validations_dont_run_on_save_after_clone_without_validation
354
- child = ChildWithValidation.new
355
- child.save :validate => false
356
- parent = ParentWithValidation.create :name => 'John', :children => [child]
357
-
358
- deep_clone_parent = parent.deep_clone :include => :children, :validate => false
359
- deep_clone_child = deep_clone_parent.children.first
360
-
361
- assert deep_clone_parent.save
362
- assert !deep_clone_parent.new_record?
363
- assert !deep_clone_child.new_record?
364
- assert !deep_clone_child.valid?
365
- assert_equal deep_clone_child.errors.messages, :name => ["can't be blank"]
366
- end
367
-
368
- def test_self_join_has_many
369
- parent_part = Part.create(:name => 'Parent')
370
- Part.create(:name => 'Child 1', :parent_part_id => parent_part.id)
371
- Part.create(:name => 'Child 2', :parent_part_id => parent_part.id)
372
-
373
- deep_clone_part = parent_part.deep_clone :include => :child_parts
374
- assert deep_clone_part.save
375
- assert_equal 2, deep_clone_part.child_parts.size
376
- end
377
-
378
- def test_should_include_has_many_through_associations
379
- subject1 = Subject.create(:name => 'subject 1')
380
- subject2 = Subject.create(:name => 'subject 2')
381
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
382
-
383
- deep_clone = student.deep_clone :include => :subjects
384
- assert_equal 2, deep_clone.subjects.size
385
- assert_equal [[student, deep_clone], [student, deep_clone]], deep_clone.subjects.map(&:students)
386
- end
387
-
388
- def test_should_include_has_one_through_associations
389
- organization = Organization.create(:name => 'organization')
390
- contractor = Contractor.create(:name => 'contractor')
391
- Contract.create(:number => 12_345, :contractor => contractor, :organization => organization)
392
-
393
- deep_clone = organization.deep_clone(:include => :contractor)
394
- assert_equal organization.contractor, deep_clone.contractor
395
- end
396
-
397
- def test_should_deep_clone_unsaved_objects
398
- jack = Pirate.new(:name => 'Jack Sparrow', :nick_name => 'Captain Jack', :age => 30)
399
- jack.mateys.build(:name => 'John')
400
-
401
- deep_clone = jack.deep_clone(:include => :mateys)
402
- assert deep_clone.new_record?
403
- assert_equal 1, deep_clone.mateys.size
404
- assert_equal 'John', deep_clone.mateys.first.name
405
- end
406
-
407
- def test_should_reject_copies_if_conditionals_are_passed
408
- subject1 = Subject.create(:name => 'subject 1')
409
- subject2 = Subject.create(:name => 'subject 2')
410
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
411
-
412
- deep_clone = student.deep_clone :include => { :subjects => { :if => lambda { |subject| subject.name == 'subject 2' } } }
413
- assert_equal 1, deep_clone.subjects.size
414
- assert_equal 'subject 2', deep_clone.subjects.first.name
415
-
416
- deep_clone = @jack.deep_clone(:include => {
417
- :treasures => { :gold_pieces => { :unless => lambda { |piece| piece.is_a?(Parrot) } } },
418
- :mateys => { :if => lambda { |matey| matey.is_a?(GoldPiece) } }
419
- })
420
-
421
- assert deep_clone.new_record?
422
- assert deep_clone.save
423
- assert_equal 1, deep_clone.treasures.size
424
- assert_equal 1, deep_clone.gold_pieces.size
425
- assert_equal 0, deep_clone.mateys.size
426
- end
427
-
428
- def test_should_properly_read_conditions_in_arrays
429
- subject1 = Subject.create(:name => 'subject 1')
430
- subject2 = Subject.create(:name => 'subject 2')
431
- student = Student.create(:name => 'Parent', :subjects => [subject1, subject2])
432
-
433
- deep_clone = student.deep_clone(:include => [:subjects => [:if => lambda { |_subject| false }]])
434
- assert deep_clone.subjects.none?
435
-
436
- deep_clone = student.deep_clone(:include => [:subjects => [:if => lambda { |_subject| true }]])
437
- assert_equal 2, deep_clone.subjects.size
438
- end
439
-
440
- def test_should_set_association_to_nil_if_conditionals_fail
441
- deep_clone = @jack.deep_clone(:include => { :ship => { :unless => lambda { |ship| ship.name == 'Black Pearl' } } })
442
- assert_nil deep_clone.ship
443
- end
444
-
445
- def test_should_reject_copies_if_conditionals_are_passed_with_associations
446
- deep_clone = @ship.deep_clone(:include => [:pirates => [:treasures, :mateys, { :unless => lambda { |pirate| pirate.name == 'Jack Sparrow' } }]])
447
-
448
- assert deep_clone.new_record?
449
- assert deep_clone.save
450
- assert_equal 0, deep_clone.pirates.size
451
-
452
- deep_clone = @ship.deep_clone(:include => [:pirates => [:treasures, :mateys, { :if => lambda { |pirate| pirate.name == 'Jack Sparrow' } }]])
453
- assert deep_clone.new_record?
454
- assert deep_clone.save
455
- assert_equal 1, deep_clone.pirates.size
456
- end
457
-
458
- def test_should_reject_copies_if_conditionals_are_passed_with_nested_many_to_many_associations
459
- @user = User.create :name => 'Jack'
460
- @order1 = Order.create
461
- @order2 = Order.create
462
- @product1 = Product.create :name => 'Paper'
463
- @product2 = Product.create :name => 'Ink'
464
- @order2.products << [@product1, @product2]
465
- @user.orders << [@order1, @order2]
466
-
467
- deep_clone = @user.deep_clone(:include => [:orders => [:products => [{ :unless => lambda { |product| product.name == 'Ink' } }]]])
468
-
469
- assert deep_clone.new_record?
470
- assert deep_clone.save
471
- assert_equal 1, deep_clone.orders.second.products.size
472
-
473
- deep_clone = @user.deep_clone(:include => [:orders => [:products => [{ :if => lambda { |product| product.name == 'Ink' } }]]])
474
- assert deep_clone.new_record?
475
- assert deep_clone.save
476
- assert_equal 1, deep_clone.orders.second.products.size
477
- end
478
-
479
- def test_should_find_in_dict_for_habtm
480
- apt = Apartment.create(:number => '101')
481
- contractor = Contractor.create(:name => 'contractor', :apartments => [apt])
482
-
483
- apt.contractors = [contractor]
484
- apt.save!
485
-
486
- building = Building.create(:name => 'Tall Building', :contractors => [contractor], :apartments => [apt])
487
-
488
- deep_clone = building.deep_clone(:include => [
489
- :apartments,
490
- {
491
- :contractors => [
492
- :apartments
493
- ]
494
- }
495
- ],
496
- :use_dictionary => true)
497
-
498
- deep_clone.save!
499
-
500
- assert_equal deep_clone.contractors.first.apartments.first.id, deep_clone.apartments.first.id
501
- assert_equal deep_clone.apartments.first.contractors.first.id, deep_clone.contractors.first.id
502
- end
503
-
504
- def test_should_not_make_attributes_dirty_for_exceptions
505
- deep_clone = @jack.deep_clone(:except => :name)
506
- assert_nil deep_clone.name
507
- refute deep_clone.name_changed?
508
- end
509
- end