deep_cloneable 2.0.2 → 3.1.0

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