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