census 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +5 -0
  3. data/Rakefile +70 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/census/data_groups_controller.rb +44 -0
  6. data/app/helpers/census_helper.rb +15 -0
  7. data/app/models/answer.rb +43 -0
  8. data/app/models/choice.rb +9 -0
  9. data/app/models/data_group.rb +10 -0
  10. data/app/models/question.rb +54 -0
  11. data/app/views/census/_question_fields.html.erb +40 -0
  12. data/app/views/census/_user_answers.html.erb +10 -0
  13. data/app/views/census/_user_questions.html.erb +10 -0
  14. data/app/views/census/data_groups/_choice_fields.html.erb +4 -0
  15. data/app/views/census/data_groups/_form.html.erb +11 -0
  16. data/app/views/census/data_groups/_question_fields.html.erb +22 -0
  17. data/app/views/census/data_groups/edit.html.erb +7 -0
  18. data/app/views/census/data_groups/index.html.erb +10 -0
  19. data/app/views/census/data_groups/new.html.erb +7 -0
  20. data/config/routes.rb +8 -0
  21. data/generators/census/USAGE +1 -0
  22. data/generators/census/census_generator.rb +39 -0
  23. data/generators/census/lib/insert_commands.rb +33 -0
  24. data/generators/census/lib/rake_commands.rb +22 -0
  25. data/generators/census/templates/README +29 -0
  26. data/generators/census/templates/census.js +10 -0
  27. data/generators/census/templates/census.rb +14 -0
  28. data/generators/census/templates/factories.rb +24 -0
  29. data/generators/census/templates/migrations/with_users.rb +60 -0
  30. data/generators/census/templates/migrations/without_users.rb +54 -0
  31. data/generators/census/templates/user.rb +3 -0
  32. data/lib/census/data_type.rb +33 -0
  33. data/lib/census/user.rb +85 -0
  34. data/lib/census.rb +1 -0
  35. data/rails/init.rb +7 -0
  36. data/shoulda_macros/census.rb +35 -0
  37. data/test/controllers/data_groups_controller_test.rb +165 -0
  38. data/test/models/answer_test.rb +44 -0
  39. data/test/models/choice_test.rb +24 -0
  40. data/test/models/data_group_test.rb +12 -0
  41. data/test/models/question_test.rb +213 -0
  42. data/test/models/user_test.rb +9 -0
  43. data/test/rails_root/app/controllers/application_controller.rb +10 -0
  44. data/test/rails_root/app/helpers/application_helper.rb +3 -0
  45. data/test/rails_root/app/models/user.rb +3 -0
  46. data/test/rails_root/config/boot.rb +110 -0
  47. data/test/rails_root/config/environment.rb +8 -0
  48. data/test/rails_root/config/environments/development.rb +17 -0
  49. data/test/rails_root/config/environments/production.rb +28 -0
  50. data/test/rails_root/config/environments/test.rb +32 -0
  51. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  52. data/test/rails_root/config/initializers/census.rb +14 -0
  53. data/test/rails_root/config/initializers/inflections.rb +10 -0
  54. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  55. data/test/rails_root/config/initializers/new_rails_defaults.rb +21 -0
  56. data/test/rails_root/config/initializers/session_store.rb +15 -0
  57. data/test/rails_root/config/routes.rb +43 -0
  58. data/test/rails_root/db/migrate/20100406160306_create_census_tables.rb +60 -0
  59. data/test/rails_root/db/schema.rb +58 -0
  60. data/test/rails_root/test/factories/census.rb +24 -0
  61. data/test/rails_root/test/performance/browsing_test.rb +9 -0
  62. data/test/rails_root/test/test_helper.rb +38 -0
  63. data/test/rails_root/vendor/gems/acts_as_list-0.1.2/lib/acts_as_list.rb +254 -0
  64. data/test/rails_root/vendor/gems/acts_as_list-0.1.2/test/list_test.rb +369 -0
  65. data/test/rails_root/vendor/gems/inverse_of-0.0.1/install.rb +1 -0
  66. data/test/rails_root/vendor/gems/inverse_of-0.0.1/lib/inverse_of.rb +293 -0
  67. data/test/rails_root/vendor/gems/inverse_of-0.0.1/rails/init.rb +1 -0
  68. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/cases/helper.rb +28 -0
  69. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/cases/inverse_associations_test.rb +567 -0
  70. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/club.rb +13 -0
  71. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/face.rb +7 -0
  72. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/interest.rb +5 -0
  73. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/man.rb +9 -0
  74. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/sponsor.rb +4 -0
  75. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/zine.rb +3 -0
  76. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/schema/schema.rb +32 -0
  77. data/test/rails_root/vendor/gems/inverse_of-0.0.1/uninstall.rb +1 -0
  78. data/test/test_helper.rb +19 -0
  79. metadata +190 -0
@@ -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,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
@@ -0,0 +1,9 @@
1
+ class Man < ActiveRecord::Base
2
+ has_one :face, :inverse_of => :man
3
+ has_one :polymorphic_face, :class_name => 'Face', :as => :polymorphic_man, :inverse_of => :polymorphic_man
4
+ has_many :interests, :inverse_of => :man
5
+ has_many :polymorphic_interests, :class_name => 'Interest', :as => :polymorphic_man, :inverse_of => :polymorphic_man
6
+ # These are "broken" inverse_of associations for the purposes of testing
7
+ has_one :dirty_face, :class_name => 'Face', :inverse_of => :dirty_man
8
+ has_many :secret_interests, :class_name => 'Interest', :inverse_of => :secret_man
9
+ end
@@ -0,0 +1,4 @@
1
+ class Sponsor < ActiveRecord::Base
2
+ belongs_to :sponsor_club, :class_name => "Club", :foreign_key => "club_id"
3
+ belongs_to :sponsorable, :polymorphic => true
4
+ end
@@ -0,0 +1,3 @@
1
+ class Zine < ActiveRecord::Base
2
+ has_many :interests, :inverse_of => :zine
3
+ end
@@ -0,0 +1,32 @@
1
+ create_table :clubs, :force => true do |t|
2
+ t.string :name
3
+ end
4
+
5
+ create_table :sponsors, :force => true do |t|
6
+ t.integer :club_id
7
+ t.integer :sponsorable_id
8
+ t.string :sponsorable_type
9
+ end
10
+
11
+ create_table :men, :force => true do |t|
12
+ t.string :name
13
+ end
14
+
15
+ create_table :faces, :force => true do |t|
16
+ t.string :description
17
+ t.integer :man_id
18
+ t.integer :polymorphic_man_id
19
+ t.string :polymorphic_man_type
20
+ end
21
+
22
+ create_table :interests, :force => true do |t|
23
+ t.string :topic
24
+ t.integer :man_id
25
+ t.integer :polymorphic_man_id
26
+ t.string :polymorphic_man_type
27
+ t.integer :zine_id
28
+ end
29
+
30
+ create_table :zines, :force => true do |t|
31
+ t.string :title
32
+ end
@@ -0,0 +1 @@
1
+ # Uninstall hook code here