inverse_of 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,567 @@
1
+ require "cases/helper"
2
+ require 'models/man'
3
+ require 'models/face'
4
+ require 'models/interest'
5
+ require 'models/zine'
6
+ require 'models/club'
7
+ require 'models/sponsor'
8
+
9
+ class InverseAssociationTests < ActiveRecord::TestCase
10
+ def test_should_allow_for_inverse_of_options_in_associations
11
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_many') do
12
+ Class.new(ActiveRecord::Base).has_many(:wheels, :inverse_of => :car)
13
+ end
14
+
15
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_one') do
16
+ Class.new(ActiveRecord::Base).has_one(:engine, :inverse_of => :car)
17
+ end
18
+
19
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on belongs_to') do
20
+ Class.new(ActiveRecord::Base).belongs_to(:car, :inverse_of => :driver)
21
+ end
22
+ end
23
+
24
+ def test_should_be_able_to_ask_a_reflection_if_it_has_an_inverse
25
+ has_one_with_inverse_ref = Man.reflect_on_association(:face)
26
+ assert has_one_with_inverse_ref.respond_to?(:has_inverse?)
27
+ assert has_one_with_inverse_ref.has_inverse?
28
+
29
+ has_many_with_inverse_ref = Man.reflect_on_association(:interests)
30
+ assert has_many_with_inverse_ref.respond_to?(:has_inverse?)
31
+ assert has_many_with_inverse_ref.has_inverse?
32
+
33
+ belongs_to_with_inverse_ref = Face.reflect_on_association(:man)
34
+ assert belongs_to_with_inverse_ref.respond_to?(:has_inverse?)
35
+ assert belongs_to_with_inverse_ref.has_inverse?
36
+
37
+ has_one_without_inverse_ref = Club.reflect_on_association(:sponsor)
38
+ assert has_one_without_inverse_ref.respond_to?(:has_inverse?)
39
+ assert !has_one_without_inverse_ref.has_inverse?
40
+
41
+ has_many_without_inverse_ref = Club.reflect_on_association(:memberships)
42
+ assert has_many_without_inverse_ref.respond_to?(:has_inverse?)
43
+ assert !has_many_without_inverse_ref.has_inverse?
44
+
45
+ belongs_to_without_inverse_ref = Sponsor.reflect_on_association(:sponsor_club)
46
+ assert belongs_to_without_inverse_ref.respond_to?(:has_inverse?)
47
+ assert !belongs_to_without_inverse_ref.has_inverse?
48
+ end
49
+
50
+ def test_should_be_able_to_ask_a_reflection_what_it_is_the_inverse_of
51
+ has_one_ref = Man.reflect_on_association(:face)
52
+ assert has_one_ref.respond_to?(:inverse_of)
53
+
54
+ has_many_ref = Man.reflect_on_association(:interests)
55
+ assert has_many_ref.respond_to?(:inverse_of)
56
+
57
+ belongs_to_ref = Face.reflect_on_association(:man)
58
+ assert belongs_to_ref.respond_to?(:inverse_of)
59
+ end
60
+
61
+ def test_inverse_of_method_should_supply_the_actual_reflection_instance_it_is_the_inverse_of
62
+ has_one_ref = Man.reflect_on_association(:face)
63
+ assert_equal Face.reflect_on_association(:man), has_one_ref.inverse_of
64
+
65
+ has_many_ref = Man.reflect_on_association(:interests)
66
+ assert_equal Interest.reflect_on_association(:man), has_many_ref.inverse_of
67
+
68
+ belongs_to_ref = Face.reflect_on_association(:man)
69
+ assert_equal Man.reflect_on_association(:face), belongs_to_ref.inverse_of
70
+ end
71
+
72
+ def test_associations_with_no_inverse_of_should_return_nil
73
+ has_one_ref = Club.reflect_on_association(:sponsor)
74
+ assert_nil has_one_ref.inverse_of
75
+
76
+ has_many_ref = Club.reflect_on_association(:memberships)
77
+ assert_nil has_many_ref.inverse_of
78
+
79
+ belongs_to_ref = Sponsor.reflect_on_association(:sponsor_club)
80
+ assert_nil belongs_to_ref.inverse_of
81
+ end
82
+ end
83
+
84
+ class InverseHasOneTests < ActiveRecord::TestCase
85
+ fixtures :men, :faces
86
+
87
+ def test_parent_instance_should_be_shared_with_child_on_find
88
+ m = men(:gordon)
89
+ f = m.face
90
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
91
+ m.name = 'Bongo'
92
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
93
+ f.man.name = 'Mungo'
94
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
95
+ end
96
+
97
+
98
+ def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find
99
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :face)
100
+ f = m.face
101
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
102
+ m.name = 'Bongo'
103
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
104
+ f.man.name = 'Mungo'
105
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
106
+
107
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :face, :order => 'faces.id')
108
+ f = m.face
109
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
110
+ m.name = 'Bongo'
111
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
112
+ f.man.name = 'Mungo'
113
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
114
+ end
115
+
116
+ def test_parent_instance_should_be_shared_with_newly_built_child
117
+ m = men(:gordon)
118
+ f = m.build_face(:description => 'haunted')
119
+ assert_not_nil f.man
120
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
121
+ m.name = 'Bongo'
122
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
123
+ f.man.name = 'Mungo'
124
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
125
+ end
126
+
127
+ def test_parent_instance_should_be_shared_with_newly_created_child
128
+ m = men(:gordon)
129
+ f = m.create_face(:description => 'haunted')
130
+ assert_not_nil f.man
131
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
132
+ m.name = 'Bongo'
133
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
134
+ f.man.name = 'Mungo'
135
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
136
+ end
137
+
138
+ def test_parent_instance_should_be_shared_with_newly_created_child_via_bang_method
139
+ m = Man.find(:first)
140
+ f = m.face.create!(:description => 'haunted')
141
+ assert_not_nil f.man
142
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
143
+ m.name = 'Bongo'
144
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
145
+ f.man.name = 'Mungo'
146
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
147
+ end
148
+
149
+ def test_parent_instance_should_be_shared_with_newly_built_child_when_we_dont_replace_existing
150
+ m = Man.find(:first)
151
+ f = m.build_face({:description => 'haunted'}, false)
152
+ assert_not_nil f.man
153
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
154
+ m.name = 'Bongo'
155
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
156
+ f.man.name = 'Mungo'
157
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
158
+ end
159
+
160
+ def test_parent_instance_should_be_shared_with_newly_created_child_when_we_dont_replace_existing
161
+ m = Man.find(:first)
162
+ f = m.create_face({:description => 'haunted'}, false)
163
+ assert_not_nil f.man
164
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
165
+ m.name = 'Bongo'
166
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
167
+ f.man.name = 'Mungo'
168
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
169
+ end
170
+
171
+ def test_parent_instance_should_be_shared_with_newly_created_child_via_bang_method_when_we_dont_replace_existing
172
+ m = Man.find(:first)
173
+ f = m.face.create!({:description => 'haunted'}, false)
174
+ assert_not_nil f.man
175
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
176
+ m.name = 'Bongo'
177
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
178
+ f.man.name = 'Mungo'
179
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
180
+ end
181
+
182
+ def test_parent_instance_should_be_shared_with_replaced_via_accessor_child
183
+ m = Man.find(:first)
184
+ f = Face.new(:description => 'haunted')
185
+ m.face = f
186
+ assert_not_nil f.man
187
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
188
+ m.name = 'Bongo'
189
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
190
+ f.man.name = 'Mungo'
191
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to replaced-child-owned instance"
192
+ end
193
+
194
+ def test_parent_instance_should_be_shared_with_replaced_via_method_child
195
+ m = Man.find(:first)
196
+ f = Face.new(:description => 'haunted')
197
+ m.face.replace(f)
198
+ assert_not_nil f.man
199
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
200
+ m.name = 'Bongo'
201
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
202
+ f.man.name = 'Mungo'
203
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to replaced-child-owned instance"
204
+ end
205
+
206
+ def test_parent_instance_should_be_shared_with_replaced_via_method_child_when_we_dont_replace_existing
207
+ m = Man.find(:first)
208
+ f = Face.new(:description => 'haunted')
209
+ m.face.replace(f, false)
210
+ assert_not_nil f.man
211
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
212
+ m.name = 'Bongo'
213
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
214
+ f.man.name = 'Mungo'
215
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to replaced-child-owned instance"
216
+ end
217
+
218
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
219
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).dirty_face }
220
+ end
221
+ end
222
+
223
+ class InverseHasManyTests < ActiveRecord::TestCase
224
+ fixtures :men, :interests
225
+
226
+ def test_parent_instance_should_be_shared_with_every_child_on_find
227
+ m = men(:gordon)
228
+ is = m.interests
229
+ is.each do |i|
230
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
231
+ m.name = 'Bongo'
232
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
233
+ i.man.name = 'Mungo'
234
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
235
+ end
236
+ end
237
+
238
+ def test_parent_instance_should_be_shared_with_eager_loaded_children
239
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :interests)
240
+ is = m.interests
241
+ is.each do |i|
242
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
243
+ m.name = 'Bongo'
244
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
245
+ i.man.name = 'Mungo'
246
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
247
+ end
248
+
249
+ m = Man.find(:first, :conditions => {:name => 'Gordon'}, :include => :interests, :order => 'interests.id')
250
+ is = m.interests
251
+ is.each do |i|
252
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
253
+ m.name = 'Bongo'
254
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
255
+ i.man.name = 'Mungo'
256
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
257
+ end
258
+ end
259
+
260
+ def test_parent_instance_should_be_shared_with_newly_built_child
261
+ m = men(:gordon)
262
+ i = m.interests.build(:topic => 'Industrial Revolution Re-enactment')
263
+ assert_not_nil i.man
264
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
265
+ m.name = 'Bongo'
266
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
267
+ i.man.name = 'Mungo'
268
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
269
+ end
270
+
271
+ def test_parent_instance_should_be_shared_with_newly_block_style_built_child
272
+ m = Man.find(:first)
273
+ i = m.interests.build {|ii| ii.topic = 'Industrial Revolution Re-enactment'}
274
+ assert_not_nil i.topic, "Child attributes supplied to build via blocks should be populated"
275
+ assert_not_nil i.man
276
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
277
+ m.name = 'Bongo'
278
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
279
+ i.man.name = 'Mungo'
280
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
281
+ end
282
+
283
+ def test_parent_instance_should_be_shared_with_newly_created_child
284
+ m = men(:gordon)
285
+ i = m.interests.create(:topic => 'Industrial Revolution Re-enactment')
286
+ assert_not_nil i.man
287
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
288
+ m.name = 'Bongo'
289
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
290
+ i.man.name = 'Mungo'
291
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
292
+ end
293
+
294
+ def test_parent_instance_should_be_shared_with_newly_created_via_bang_method_child
295
+ m = Man.find(:first)
296
+ i = m.interests.create!(:topic => 'Industrial Revolution Re-enactment')
297
+ assert_not_nil i.man
298
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
299
+ m.name = 'Bongo'
300
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
301
+ i.man.name = 'Mungo'
302
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
303
+ end
304
+
305
+ def test_parent_instance_should_be_shared_with_newly_block_style_created_child
306
+ m = Man.find(:first)
307
+ i = m.interests.create {|ii| ii.topic = 'Industrial Revolution Re-enactment'}
308
+ assert_not_nil i.topic, "Child attributes supplied to create via blocks should be populated"
309
+ assert_not_nil i.man
310
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
311
+ m.name = 'Bongo'
312
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
313
+ i.man.name = 'Mungo'
314
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
315
+ end
316
+
317
+ def test_parent_instance_should_be_shared_with_poked_in_child
318
+ m = men(:gordon)
319
+ i = Interest.create(:topic => 'Industrial Revolution Re-enactment')
320
+ m.interests << i
321
+ assert_not_nil i.man
322
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
323
+ m.name = 'Bongo'
324
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
325
+ i.man.name = 'Mungo'
326
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
327
+ end
328
+
329
+ def test_parent_instance_should_be_shared_with_replaced_via_accessor_children
330
+ m = Man.find(:first)
331
+ i = Interest.new(:topic => 'Industrial Revolution Re-enactment')
332
+ m.interests = [i]
333
+ assert_not_nil i.man
334
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
335
+ m.name = 'Bongo'
336
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
337
+ i.man.name = 'Mungo'
338
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to replaced-child-owned instance"
339
+ end
340
+
341
+ def test_parent_instance_should_be_shared_with_replaced_via_method_children
342
+ m = Man.find(:first)
343
+ i = Interest.new(:topic => 'Industrial Revolution Re-enactment')
344
+ m.interests.replace([i])
345
+ assert_not_nil i.man
346
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
347
+ m.name = 'Bongo'
348
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
349
+ i.man.name = 'Mungo'
350
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to replaced-child-owned instance"
351
+ end
352
+
353
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
354
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).secret_interests }
355
+ end
356
+ end
357
+
358
+ class InverseBelongsToTests < ActiveRecord::TestCase
359
+ fixtures :men, :faces, :interests
360
+
361
+ def test_child_instance_should_be_shared_with_parent_on_find
362
+ f = faces(:trusting)
363
+ m = f.man
364
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
365
+ f.description = 'gormless'
366
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
367
+ m.face.description = 'pleasing'
368
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
369
+ end
370
+
371
+ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
372
+ f = Face.find(:first, :include => :man, :conditions => {:description => 'trusting'})
373
+ m = f.man
374
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
375
+ f.description = 'gormless'
376
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
377
+ m.face.description = 'pleasing'
378
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
379
+
380
+ f = Face.find(:first, :include => :man, :order => 'men.id', :conditions => {:description => 'trusting'})
381
+ m = f.man
382
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
383
+ f.description = 'gormless'
384
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
385
+ m.face.description = 'pleasing'
386
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
387
+ end
388
+
389
+ def test_child_instance_should_be_shared_with_newly_built_parent
390
+ f = faces(:trusting)
391
+ m = f.build_man(:name => 'Charles')
392
+ assert_not_nil m.face
393
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
394
+ f.description = 'gormless'
395
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
396
+ m.face.description = 'pleasing'
397
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to just-built-parent-owned instance"
398
+ end
399
+
400
+ def test_child_instance_should_be_shared_with_newly_created_parent
401
+ f = faces(:trusting)
402
+ m = f.create_man(:name => 'Charles')
403
+ assert_not_nil m.face
404
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
405
+ f.description = 'gormless'
406
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
407
+ m.face.description = 'pleasing'
408
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to newly-created-parent-owned instance"
409
+ end
410
+
411
+ def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
412
+ i = interests(:trainspotting)
413
+ m = i.man
414
+ assert_not_nil m.interests
415
+ iz = m.interests.detect {|iz| iz.id == i.id}
416
+ assert_not_nil iz
417
+ assert_equal i.topic, iz.topic, "Interest topics should be the same before changes to child"
418
+ i.topic = 'Eating cheese with a spoon'
419
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to child"
420
+ iz.topic = 'Cow tipping'
421
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to parent-owned instance"
422
+ end
423
+
424
+ def test_child_instance_should_be_shared_with_replaced_via_accessor_parent
425
+ f = Face.find(:first)
426
+ m = Man.new(:name => 'Charles')
427
+ f.man = m
428
+ assert_not_nil m.face
429
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
430
+ f.description = 'gormless'
431
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
432
+ m.face.description = 'pleasing'
433
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to replaced-parent-owned instance"
434
+ end
435
+
436
+ def test_child_instance_should_be_shared_with_replaced_via_method_parent
437
+ f = faces(:trusting)
438
+ assert_not_nil f.man
439
+ m = Man.new(:name => 'Charles')
440
+ f.man.replace(m)
441
+ assert_not_nil m.face
442
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
443
+ f.description = 'gormless'
444
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
445
+ m.face.description = 'pleasing'
446
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to replaced-parent-owned instance"
447
+ end
448
+
449
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
450
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_man }
451
+ end
452
+ end
453
+
454
+ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase
455
+ fixtures :men, :faces, :interests
456
+
457
+ def test_child_instance_should_be_shared_with_parent_on_find
458
+ f = Face.find(:first, :conditions => {:description => 'confused'})
459
+ m = f.polymorphic_man
460
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same before changes to child instance"
461
+ f.description = 'gormless'
462
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to child instance"
463
+ m.polymorphic_face.description = 'pleasing'
464
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to parent-owned instance"
465
+ end
466
+
467
+ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
468
+ f = Face.find(:first, :conditions => {:description => 'confused'}, :include => :man)
469
+ m = f.polymorphic_man
470
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same before changes to child instance"
471
+ f.description = 'gormless'
472
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to child instance"
473
+ m.polymorphic_face.description = 'pleasing'
474
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to parent-owned instance"
475
+
476
+ f = Face.find(:first, :conditions => {:description => 'confused'}, :include => :man, :order => 'men.id')
477
+ m = f.polymorphic_man
478
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same before changes to child instance"
479
+ f.description = 'gormless'
480
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to child instance"
481
+ m.polymorphic_face.description = 'pleasing'
482
+ assert_equal f.description, m.polymorphic_face.description, "Description of face should be the same after changes to parent-owned instance"
483
+ end
484
+
485
+ def test_child_instance_should_be_shared_with_replaced_via_accessor_parent
486
+ face = faces(:confused)
487
+ old_man = face.polymorphic_man
488
+ new_man = Man.new
489
+
490
+ assert_not_nil face.polymorphic_man
491
+ face.polymorphic_man = new_man
492
+
493
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same before changes to parent instance"
494
+ face.description = 'Bongo'
495
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same after changes to parent instance"
496
+ new_man.polymorphic_face.description = 'Mungo'
497
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same after changes to replaced-parent-owned instance"
498
+ end
499
+
500
+ def test_child_instance_should_be_shared_with_replaced_via_method_parent
501
+ face = faces(:confused)
502
+ old_man = face.polymorphic_man
503
+ new_man = Man.new
504
+
505
+ assert_not_nil face.polymorphic_man
506
+ face.polymorphic_man.replace(new_man)
507
+
508
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same before changes to parent instance"
509
+ face.description = 'Bongo'
510
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same after changes to parent instance"
511
+ new_man.polymorphic_face.description = 'Mungo'
512
+ assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same after changes to replaced-parent-owned instance"
513
+ end
514
+
515
+ def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
516
+ i = interests(:llama_wrangling)
517
+ m = i.polymorphic_man
518
+ assert_not_nil m.polymorphic_interests
519
+ iz = m.polymorphic_interests.detect {|iz| iz.id == i.id}
520
+ assert_not_nil iz
521
+ assert_equal i.topic, iz.topic, "Interest topics should be the same before changes to child"
522
+ i.topic = 'Eating cheese with a spoon'
523
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to child"
524
+ iz.topic = 'Cow tipping'
525
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to parent-owned instance"
526
+ end
527
+
528
+ def test_trying_to_access_inverses_that_dont_exist_shouldnt_raise_an_error
529
+ # Ideally this would, if only for symmetry's sake with other association types
530
+ assert_nothing_raised(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_polymorphic_man }
531
+ end
532
+
533
+ def test_trying_to_set_polymorphic_inverses_that_dont_exist_at_all_should_raise_an_error
534
+ # fails because no class has the correct inverse_of for horrible_polymorphic_man
535
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_polymorphic_man = Man.first }
536
+ end
537
+
538
+ def test_trying_to_set_polymorphic_inverses_that_dont_exist_on_the_instance_being_set_should_raise_an_error
539
+ # passes because Man does have the correct inverse_of
540
+ assert_nothing_raised(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).polymorphic_man = Man.first }
541
+ # fails because Interest does have the correct inverse_of
542
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).polymorphic_man = Interest.first }
543
+ end
544
+ end
545
+
546
+ # NOTE - these tests might not be meaningful, ripped as they were from the parental_control plugin
547
+ # which would guess the inverse rather than look for an explicit configuration option.
548
+ class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase
549
+ fixtures :men, :interests, :zines
550
+
551
+ def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models
552
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
553
+ i = Interest.find(:first)
554
+ z = i.zine
555
+ m = i.man
556
+ end
557
+ end
558
+
559
+ def test_that_we_can_create_associations_that_have_the_same_reciprocal_name_from_different_models
560
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
561
+ i = Interest.find(:first)
562
+ i.build_zine(:title => 'Get Some in Winter! 2008')
563
+ i.build_man(:name => 'Gordon')
564
+ i.save!
565
+ end
566
+ end
567
+ end
@@ -0,0 +1,6 @@
1
+ boring_club:
2
+ name: Banana appreciation society
3
+ moustache_club:
4
+ name: Moustache and Eyebrow Fancier Club
5
+ crazy_club:
6
+ name: Skull and bones
@@ -0,0 +1,11 @@
1
+ trusting:
2
+ description: trusting
3
+ man: gordon
4
+
5
+ weather_beaten:
6
+ description: weather beaten
7
+ man: steve
8
+
9
+ confused:
10
+ description: confused
11
+ polymorphic_man: gordon (Man)
@@ -0,0 +1,33 @@
1
+ trainspotting:
2
+ topic: Trainspotting
3
+ zine: staying_in
4
+ man: gordon
5
+
6
+ birdwatching:
7
+ topic: Birdwatching
8
+ zine: staying_in
9
+ man: gordon
10
+
11
+ stamp_collecting:
12
+ topic: Stamp Collecting
13
+ zine: staying_in
14
+ man: gordon
15
+
16
+ hunting:
17
+ topic: Hunting
18
+ zine: going_out
19
+ man: steve
20
+
21
+ woodsmanship:
22
+ topic: Woodsmanship
23
+ zine: going_out
24
+ man: steve
25
+
26
+ survival:
27
+ topic: Survival
28
+ zine: going_out
29
+ man: steve
30
+
31
+ llama_wrangling:
32
+ topic: Llama Wrangling
33
+ polymorphic_man: gordon (Man)
@@ -0,0 +1,5 @@
1
+ gordon:
2
+ name: Gordon
3
+
4
+ steve:
5
+ name: Steve
@@ -0,0 +1,9 @@
1
+ moustache_club_sponsor_for_groucho:
2
+ sponsor_club: moustache_club
3
+ sponsorable: groucho (Member)
4
+ boring_club_sponsor_for_groucho:
5
+ sponsor_club: boring_club
6
+ sponsorable: some_other_guy (Member)
7
+ crazy_club_sponsor_for_groucho:
8
+ sponsor_club: crazy_club
9
+ sponsorable: some_other_guy (Member)
@@ -0,0 +1,5 @@
1
+ staying_in:
2
+ title: Staying in '08
3
+
4
+ going_out:
5
+ title: Outdoor Pursuits 2k+8
@@ -0,0 +1,13 @@
1
+ class Club < ActiveRecord::Base
2
+ has_many :memberships
3
+ has_many :members, :through => :memberships
4
+ has_many :current_memberships
5
+ has_one :sponsor
6
+ has_one :sponsored_member, :through => :sponsor, :source => :sponsorable, :source_type => "Member"
7
+
8
+ private
9
+
10
+ def private_method
11
+ "I'm sorry sir, this is a *private* club, not a *pirate* club"
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class Face < ActiveRecord::Base
2
+ belongs_to :man, :inverse_of => :face
3
+ belongs_to :polymorphic_man, :polymorphic => true, :inverse_of => :polymorphic_face
4
+ # These is a "broken" inverse_of for the purposes of testing
5
+ belongs_to :horrible_man, :class_name => 'Man', :inverse_of => :horrible_face
6
+ belongs_to :horrible_polymorphic_man, :polymorphic => true, :inverse_of => :horrible_polymorphic_face
7
+ end
@@ -0,0 +1,5 @@
1
+ class Interest < ActiveRecord::Base
2
+ belongs_to :man, :inverse_of => :interests
3
+ belongs_to :polymorphic_man, :polymorphic => true, :inverse_of => :polymorphic_interests
4
+ belongs_to :zine, :inverse_of => :interests
5
+ end