inverse_of 0.0.1

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.
@@ -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