has_many_polymorphs 2.2

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.
Files changed (177) hide show
  1. data/CHANGELOG +86 -0
  2. data/LICENSE +184 -0
  3. data/Manifest +173 -0
  4. data/README +205 -0
  5. data/Rakefile +28 -0
  6. data/TODO +2 -0
  7. data/examples/hmph.rb +69 -0
  8. data/generators/tagging/tagging_generator.rb +97 -0
  9. data/generators/tagging/templates/migration.rb +28 -0
  10. data/generators/tagging/templates/tag.rb +39 -0
  11. data/generators/tagging/templates/tag_test.rb +15 -0
  12. data/generators/tagging/templates/tagging.rb +16 -0
  13. data/generators/tagging/templates/tagging_extensions.rb +203 -0
  14. data/generators/tagging/templates/tagging_test.rb +85 -0
  15. data/generators/tagging/templates/taggings.yml +23 -0
  16. data/generators/tagging/templates/tags.yml +7 -0
  17. data/has_many_polymorphs.gemspec +36 -0
  18. data/init.rb +2 -0
  19. data/lib/has_many_polymorphs/association.rb +160 -0
  20. data/lib/has_many_polymorphs/autoload.rb +69 -0
  21. data/lib/has_many_polymorphs/base.rb +60 -0
  22. data/lib/has_many_polymorphs/class_methods.rb +600 -0
  23. data/lib/has_many_polymorphs/configuration.rb +19 -0
  24. data/lib/has_many_polymorphs/debugging_tools.rb +103 -0
  25. data/lib/has_many_polymorphs/rake_task_redefine_task.rb +35 -0
  26. data/lib/has_many_polymorphs/reflection.rb +58 -0
  27. data/lib/has_many_polymorphs/support_methods.rb +88 -0
  28. data/lib/has_many_polymorphs.rb +27 -0
  29. data/test/fixtures/bow_wows.yml +10 -0
  30. data/test/fixtures/cats.yml +18 -0
  31. data/test/fixtures/eaters_foodstuffs.yml +0 -0
  32. data/test/fixtures/fish.yml +12 -0
  33. data/test/fixtures/frogs.yml +5 -0
  34. data/test/fixtures/keep_your_enemies_close.yml +0 -0
  35. data/test/fixtures/little_whale_pupils.yml +0 -0
  36. data/test/fixtures/people.yml +7 -0
  37. data/test/fixtures/petfoods.yml +11 -0
  38. data/test/fixtures/whales.yml +5 -0
  39. data/test/fixtures/wild_boars.yml +10 -0
  40. data/test/generator/tagging_generator_test.rb +42 -0
  41. data/test/integration/app/README +182 -0
  42. data/test/integration/app/Rakefile +19 -0
  43. data/test/integration/app/app/controllers/application.rb +7 -0
  44. data/test/integration/app/app/controllers/bones_controller.rb +5 -0
  45. data/test/integration/app/app/helpers/addresses_helper.rb +2 -0
  46. data/test/integration/app/app/helpers/application_helper.rb +3 -0
  47. data/test/integration/app/app/helpers/bones_helper.rb +2 -0
  48. data/test/integration/app/app/helpers/sellers_helper.rb +28 -0
  49. data/test/integration/app/app/helpers/states_helper.rb +2 -0
  50. data/test/integration/app/app/helpers/users_helper.rb +2 -0
  51. data/test/integration/app/app/models/bone.rb +2 -0
  52. data/test/integration/app/app/models/double_sti_parent.rb +2 -0
  53. data/test/integration/app/app/models/double_sti_parent_relationship.rb +2 -0
  54. data/test/integration/app/app/models/organic_substance.rb +2 -0
  55. data/test/integration/app/app/models/single_sti_parent.rb +4 -0
  56. data/test/integration/app/app/models/single_sti_parent_relationship.rb +4 -0
  57. data/test/integration/app/app/models/stick.rb +2 -0
  58. data/test/integration/app/app/models/stone.rb +2 -0
  59. data/test/integration/app/app/views/addresses/edit.html.erb +12 -0
  60. data/test/integration/app/app/views/addresses/index.html.erb +18 -0
  61. data/test/integration/app/app/views/addresses/new.html.erb +11 -0
  62. data/test/integration/app/app/views/addresses/show.html.erb +3 -0
  63. data/test/integration/app/app/views/bones/index.rhtml +5 -0
  64. data/test/integration/app/app/views/layouts/addresses.html.erb +17 -0
  65. data/test/integration/app/app/views/layouts/sellers.html.erb +17 -0
  66. data/test/integration/app/app/views/layouts/states.html.erb +17 -0
  67. data/test/integration/app/app/views/layouts/users.html.erb +17 -0
  68. data/test/integration/app/app/views/sellers/edit.html.erb +12 -0
  69. data/test/integration/app/app/views/sellers/index.html.erb +20 -0
  70. data/test/integration/app/app/views/sellers/new.html.erb +11 -0
  71. data/test/integration/app/app/views/sellers/show.html.erb +3 -0
  72. data/test/integration/app/app/views/states/edit.html.erb +12 -0
  73. data/test/integration/app/app/views/states/index.html.erb +19 -0
  74. data/test/integration/app/app/views/states/new.html.erb +11 -0
  75. data/test/integration/app/app/views/states/show.html.erb +3 -0
  76. data/test/integration/app/app/views/users/edit.html.erb +12 -0
  77. data/test/integration/app/app/views/users/index.html.erb +22 -0
  78. data/test/integration/app/app/views/users/new.html.erb +11 -0
  79. data/test/integration/app/app/views/users/show.html.erb +3 -0
  80. data/test/integration/app/config/boot.rb +110 -0
  81. data/test/integration/app/config/database.yml +17 -0
  82. data/test/integration/app/config/environment.rb +19 -0
  83. data/test/integration/app/config/environment.rb.canonical +19 -0
  84. data/test/integration/app/config/environments/development.rb +9 -0
  85. data/test/integration/app/config/environments/production.rb +18 -0
  86. data/test/integration/app/config/environments/test.rb +19 -0
  87. data/test/integration/app/config/locomotive.yml +6 -0
  88. data/test/integration/app/config/routes.rb +33 -0
  89. data/test/integration/app/config/ultrasphinx/default.base +56 -0
  90. data/test/integration/app/config/ultrasphinx/development.conf.canonical +155 -0
  91. data/test/integration/app/db/migrate/001_create_sticks.rb +11 -0
  92. data/test/integration/app/db/migrate/002_create_stones.rb +11 -0
  93. data/test/integration/app/db/migrate/003_create_organic_substances.rb +11 -0
  94. data/test/integration/app/db/migrate/004_create_bones.rb +8 -0
  95. data/test/integration/app/db/migrate/005_create_single_sti_parents.rb +11 -0
  96. data/test/integration/app/db/migrate/006_create_double_sti_parents.rb +11 -0
  97. data/test/integration/app/db/migrate/007_create_single_sti_parent_relationships.rb +13 -0
  98. data/test/integration/app/db/migrate/008_create_double_sti_parent_relationships.rb +14 -0
  99. data/test/integration/app/db/migrate/009_create_library_model.rb +11 -0
  100. data/test/integration/app/doc/README_FOR_APP +2 -0
  101. data/test/integration/app/generators/commenting_generator_test.rb +83 -0
  102. data/test/integration/app/lib/library_model.rb +2 -0
  103. data/test/integration/app/public/404.html +30 -0
  104. data/test/integration/app/public/500.html +30 -0
  105. data/test/integration/app/public/dispatch.cgi +10 -0
  106. data/test/integration/app/public/dispatch.fcgi +24 -0
  107. data/test/integration/app/public/dispatch.rb +10 -0
  108. data/test/integration/app/public/favicon.ico +0 -0
  109. data/test/integration/app/public/images/rails.png +0 -0
  110. data/test/integration/app/public/index.html +277 -0
  111. data/test/integration/app/public/javascripts/application.js +2 -0
  112. data/test/integration/app/public/javascripts/controls.js +833 -0
  113. data/test/integration/app/public/javascripts/dragdrop.js +942 -0
  114. data/test/integration/app/public/javascripts/effects.js +1088 -0
  115. data/test/integration/app/public/javascripts/prototype.js +2515 -0
  116. data/test/integration/app/public/robots.txt +1 -0
  117. data/test/integration/app/public/stylesheets/scaffold.css +74 -0
  118. data/test/integration/app/script/about +3 -0
  119. data/test/integration/app/script/breakpointer +3 -0
  120. data/test/integration/app/script/console +3 -0
  121. data/test/integration/app/script/destroy +3 -0
  122. data/test/integration/app/script/generate +3 -0
  123. data/test/integration/app/script/performance/benchmarker +3 -0
  124. data/test/integration/app/script/performance/profiler +3 -0
  125. data/test/integration/app/script/plugin +3 -0
  126. data/test/integration/app/script/process/inspector +3 -0
  127. data/test/integration/app/script/process/reaper +3 -0
  128. data/test/integration/app/script/process/spawner +3 -0
  129. data/test/integration/app/script/runner +3 -0
  130. data/test/integration/app/script/server +3 -0
  131. data/test/integration/app/test/fixtures/double_sti_parent_relationships.yml +7 -0
  132. data/test/integration/app/test/fixtures/double_sti_parents.yml +7 -0
  133. data/test/integration/app/test/fixtures/organic_substances.yml +5 -0
  134. data/test/integration/app/test/fixtures/single_sti_parent_relationships.yml +7 -0
  135. data/test/integration/app/test/fixtures/single_sti_parents.yml +7 -0
  136. data/test/integration/app/test/fixtures/sticks.yml +7 -0
  137. data/test/integration/app/test/fixtures/stones.yml +7 -0
  138. data/test/integration/app/test/functional/addresses_controller_test.rb +57 -0
  139. data/test/integration/app/test/functional/bones_controller_test.rb +8 -0
  140. data/test/integration/app/test/functional/sellers_controller_test.rb +57 -0
  141. data/test/integration/app/test/functional/states_controller_test.rb +57 -0
  142. data/test/integration/app/test/functional/users_controller_test.rb +57 -0
  143. data/test/integration/app/test/test_helper.rb +8 -0
  144. data/test/integration/app/test/unit/bone_test.rb +8 -0
  145. data/test/integration/app/test/unit/double_sti_parent_relationship_test.rb +8 -0
  146. data/test/integration/app/test/unit/double_sti_parent_test.rb +8 -0
  147. data/test/integration/app/test/unit/organic_substance_test.rb +8 -0
  148. data/test/integration/app/test/unit/single_sti_parent_relationship_test.rb +8 -0
  149. data/test/integration/app/test/unit/single_sti_parent_test.rb +8 -0
  150. data/test/integration/app/test/unit/stick_test.rb +8 -0
  151. data/test/integration/app/test/unit/stone_test.rb +8 -0
  152. data/test/integration/server_test.rb +43 -0
  153. data/test/models/aquatic/fish.rb +5 -0
  154. data/test/models/aquatic/pupils_whale.rb +7 -0
  155. data/test/models/aquatic/whale.rb +15 -0
  156. data/test/models/beautiful_fight_relationship.rb +26 -0
  157. data/test/models/canine.rb +9 -0
  158. data/test/models/cat.rb +5 -0
  159. data/test/models/dog.rb +18 -0
  160. data/test/models/eaters_foodstuff.rb +8 -0
  161. data/test/models/frog.rb +4 -0
  162. data/test/models/kitten.rb +3 -0
  163. data/test/models/parentship.rb +4 -0
  164. data/test/models/person.rb +9 -0
  165. data/test/models/petfood.rb +39 -0
  166. data/test/models/tabby.rb +2 -0
  167. data/test/models/wild_boar.rb +3 -0
  168. data/test/modules/extension_module.rb +9 -0
  169. data/test/modules/other_extension_module.rb +9 -0
  170. data/test/patches/symlinked_plugins_1.2.6.diff +46 -0
  171. data/test/schema.rb +87 -0
  172. data/test/setup.rb +14 -0
  173. data/test/test_helper.rb +52 -0
  174. data/test/unit/has_many_polymorphs_test.rb +713 -0
  175. data.tar.gz.sig +1 -0
  176. metadata +279 -0
  177. metadata.gz.sig +0 -0
@@ -0,0 +1,713 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ require 'dog'
4
+ require 'wild_boar'
5
+ require 'frog'
6
+ require 'cat'
7
+ require 'kitten'
8
+ require 'aquatic/whale'
9
+ require 'aquatic/fish'
10
+ require 'aquatic/pupils_whale'
11
+ require 'beautiful_fight_relationship'
12
+
13
+ class PolymorphTest < ActiveSupport::TestCase
14
+
15
+ set_fixture_class :bow_wows => Dog
16
+ set_fixture_class :keep_your_enemies_close => BeautifulFightRelationship
17
+ set_fixture_class :whales => Aquatic::Whale
18
+ set_fixture_class :fish => Aquatic::Fish
19
+ set_fixture_class :little_whale_pupils => Aquatic::PupilsWhale
20
+
21
+ fixtures :cats, :bow_wows, :frogs, :wild_boars, :eaters_foodstuffs, :petfoods,
22
+ :fish, :whales, :little_whale_pupils, :keep_your_enemies_close, :people
23
+
24
+ def setup
25
+ @association_error = ActiveRecord::Associations::PolymorphicError
26
+ @kibbles = Petfood.find(1)
27
+ @bits = Petfood.find(2)
28
+ @shamu = Aquatic::Whale.find(1)
29
+ @swimmy = Aquatic::Fish.find(1)
30
+ @rover = Dog.find(1)
31
+ @spot = Dog.find(2)
32
+ @puma = WildBoar.find(1)
33
+ @chloe = Kitten.find(1)
34
+ @alice = Kitten.find(2)
35
+ @toby = Tabby.find(3)
36
+ @froggy = Frog.find(1)
37
+
38
+ @join_count = EatersFoodstuff.count
39
+ @kibbles_eaters_count = @kibbles.eaters.size
40
+ @bits_eaters_count = @bits.eaters.size
41
+
42
+ @double_join_count = BeautifulFightRelationship.count
43
+ @alice_enemies_count = @alice.enemies.size
44
+ end
45
+
46
+ def test_all_relationship_validities
47
+ # q = []
48
+ # ObjectSpace.each_object(Class){|c| q << c if c.ancestors.include? ActiveRecord::Base }
49
+ # q.each{|c| puts "#{c.name}.reflect_on_all_associations.map(&:check_validity!)"}
50
+ Petfood.reflect_on_all_associations.map(&:check_validity!)
51
+ Tabby.reflect_on_all_associations.map(&:check_validity!)
52
+ Kitten.reflect_on_all_associations.map(&:check_validity!)
53
+ Dog.reflect_on_all_associations.map(&:check_validity!)
54
+ Canine.reflect_on_all_associations.map(&:check_validity!)
55
+ Aquatic::Fish.reflect_on_all_associations.map(&:check_validity!)
56
+ EatersFoodstuff.reflect_on_all_associations.map(&:check_validity!)
57
+ WildBoar.reflect_on_all_associations.map(&:check_validity!)
58
+ Frog.reflect_on_all_associations.map(&:check_validity!)
59
+ Cat.reflect_on_all_associations.map(&:check_validity!)
60
+ BeautifulFightRelationship.reflect_on_all_associations.map(&:check_validity!)
61
+ Person.reflect_on_all_associations.map(&:check_validity!)
62
+ Parentship.reflect_on_all_associations.map(&:check_validity!)
63
+ Aquatic::Whale.reflect_on_all_associations.map(&:check_validity!)
64
+ Aquatic::PupilsWhale.reflect_on_all_associations.map(&:check_validity!)
65
+ end
66
+
67
+ def test_assignment
68
+ assert @kibbles.eaters.blank?
69
+ assert @kibbles.eaters.push(Cat.find_by_name('Chloe'))
70
+ assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
71
+
72
+ @kibbles.reload
73
+ assert_equal @kibbles_eaters_count, @kibbles.eaters.count
74
+ end
75
+
76
+ def test_duplicate_assignment
77
+ # try to add a duplicate item when :ignore_duplicates is false
78
+ @kibbles.eaters.push(@alice)
79
+ assert @kibbles.eaters.any? {|obj| obj == @alice}
80
+ @kibbles.eaters.push(@alice)
81
+ assert_equal @kibbles_eaters_count + 2, @kibbles.eaters.count
82
+ assert_equal @join_count + 2, EatersFoodstuff.count
83
+ end
84
+
85
+ def test_create_and_push
86
+ assert @kibbles.eaters.push(@spot)
87
+ assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
88
+ assert @kibbles.eaters << @rover
89
+ assert @kibbles.eaters << Kitten.create(:name => "Miranda")
90
+ assert_equal @kibbles_eaters_count += 2, @kibbles.eaters.length
91
+
92
+ @kibbles.reload
93
+ assert_equal @kibbles_eaters_count, @kibbles.eaters.length
94
+
95
+ # test that ids and new flags were set appropriately
96
+ assert_not_nil @kibbles.eaters[0].id
97
+ assert !@kibbles.eaters[1].new_record?
98
+ end
99
+
100
+ def test_reload
101
+ assert @kibbles.reload
102
+ assert @kibbles.eaters.reload
103
+ end
104
+
105
+ def test_add_join_record
106
+ assert_equal Kitten, @chloe.class
107
+ assert join = EatersFoodstuff.new(:foodstuff_id => @bits.id, :eater_id => @chloe.id, :eater_type => @chloe.class.name )
108
+ assert join.save!
109
+ assert join.id
110
+ assert_equal @join_count + 1, EatersFoodstuff.count
111
+
112
+ #assert_equal @bits_eaters_count, @bits.eaters.size # Doesn't behave this way on latest edge anymore
113
+ assert_equal @bits_eaters_count + 1, @bits.eaters.count # SQL
114
+
115
+ # reload; is the new association there?
116
+ assert @bits.eaters.reload
117
+ assert @bits.eaters.any? {|obj| obj == @chloe}
118
+ end
119
+
120
+ def test_build_join_record_on_association
121
+ assert_equal Kitten, @chloe.class
122
+ assert join = @chloe.eaters_foodstuffs.build(:foodstuff => @bits)
123
+ # assert_equal join.eater_type, @chloe.class.name # will be STI parent type
124
+ assert join.save!
125
+ assert join.id
126
+ assert_equal @join_count + 1, EatersFoodstuff.count
127
+
128
+ assert @bits.eaters.reload
129
+ assert @bits.eaters.any? {|obj| obj == @chloe}
130
+ end
131
+
132
+ # not supporting this, since has_many :through doesn't support it either
133
+ # def test_add_unsaved
134
+ # # add an unsaved item
135
+ # assert @bits.eaters << Kitten.new(:name => "Bridget")
136
+ # assert_nil Kitten.find_by_name("Bridget")
137
+ # assert_equal @bits_eaters_count + 1, @bits.eaters.count
138
+ #
139
+ # assert @bits.save
140
+ # @bits.reload
141
+ # assert_equal @bits_eaters_count + 1, @bits.eaters.count
142
+ #
143
+ # end
144
+
145
+ def test_self_reference
146
+ assert @kibbles.eaters << @bits
147
+ assert_equal @kibbles_eaters_count += 1, @kibbles.eaters.count
148
+ assert @kibbles.eaters.any? {|obj| obj == @bits}
149
+ @kibbles.reload
150
+ assert @kibbles.foodstuffs_of_eaters.blank?
151
+
152
+ @bits.reload
153
+ assert @bits.foodstuffs_of_eaters.any? {|obj| obj == @kibbles}
154
+ assert_equal [@kibbles], @bits.foodstuffs_of_eaters
155
+ end
156
+
157
+ def test_remove
158
+ assert @kibbles.eaters << @chloe
159
+ @kibbles.reload
160
+ assert @kibbles.eaters.delete(@kibbles.eaters[0])
161
+ assert_equal @kibbles_eaters_count, @kibbles.eaters.count
162
+ end
163
+
164
+ def test_destroy
165
+ assert @kibbles.eaters.push(@chloe)
166
+ @kibbles.reload
167
+ assert @kibbles.eaters.length > 0
168
+ assert @kibbles.eaters[0].destroy
169
+ @kibbles.reload
170
+ assert_equal @kibbles_eaters_count, @kibbles.eaters.count
171
+ end
172
+
173
+ def test_clear
174
+ @kibbles.eaters << [@chloe, @spot, @rover]
175
+ @kibbles.reload
176
+ assert @kibbles.eaters.clear.blank?
177
+ assert @kibbles.eaters.blank?
178
+ @kibbles.reload
179
+ assert @kibbles.eaters.blank?
180
+ end
181
+
182
+ def test_individual_collections
183
+ assert @kibbles.eaters.push(@chloe)
184
+ # check if individual collections work
185
+ assert_equal @kibbles.eater_kittens.length, 1
186
+ assert @kibbles.eater_dogs
187
+ assert 1, @rover.eaters_foodstuffs.count
188
+ end
189
+
190
+ def test_individual_collections_push
191
+ assert_equal [@chloe], (@kibbles.eater_kittens << @chloe)
192
+ @kibbles.reload
193
+ assert @kibbles.eaters.any? {|obj| obj == @chloe}
194
+ assert @kibbles.eater_kittens.any? {|obj| obj == @chloe}
195
+ assert !@kibbles.eater_dogs.any? {|obj| obj == @chloe}
196
+ end
197
+
198
+ def test_individual_collections_delete
199
+ @kibbles.eaters << [@chloe, @spot, @rover]
200
+ @kibbles.reload
201
+ assert_equal [@chloe], @kibbles.eater_kittens.delete(@chloe)
202
+ assert @kibbles.eater_kittens.empty?
203
+ @kibbles.eater_kittens.delete(@chloe) # what should this return?
204
+
205
+ @kibbles.reload
206
+ assert @kibbles.eater_kittens.empty?
207
+ assert @kibbles.eater_dogs.any? {|obj| obj == @spot}
208
+ end
209
+
210
+ def test_individual_collections_clear
211
+ @kibbles.eaters << [@chloe, @spot, @rover]
212
+ @kibbles.reload
213
+
214
+ assert_equal [], @kibbles.eater_kittens.clear
215
+ assert @kibbles.eater_kittens.empty?
216
+ assert_equal 2, @kibbles.eaters.size
217
+
218
+ assert @kibbles.eater_kittens.empty?
219
+ assert_equal 2, @kibbles.eaters.size
220
+ assert !@kibbles.eater_kittens.any? {|obj| obj == @chloe}
221
+ assert !@kibbles.eaters.any? {|obj| obj == @chloe}
222
+
223
+ @kibbles.reload
224
+ assert @kibbles.eater_kittens.empty?
225
+ assert_equal 2, @kibbles.eaters.size
226
+ assert !@kibbles.eater_kittens.any? {|obj| obj == @chloe}
227
+ assert !@kibbles.eaters.any? {|obj| obj == @chloe}
228
+ end
229
+
230
+ def test_childrens_individual_collections
231
+ assert Cat.find_by_name('Chloe').eaters_foodstuffs
232
+ assert @kibbles.eaters_foodstuffs
233
+ end
234
+
235
+ def test_self_referential_join_tables
236
+ # check that the self-reference join tables go the right ways
237
+ assert_equal @kibbles_eaters_count, @kibbles.eaters_foodstuffs.count
238
+ assert_equal @kibbles.eaters_foodstuffs.count, @kibbles.eaters_foodstuffs_as_child.count
239
+ end
240
+
241
+ def test_dependent
242
+ assert @kibbles.eaters << @chloe
243
+ @kibbles.reload
244
+
245
+ # delete ourself and see if :dependent was obeyed
246
+ dependent_rows = @kibbles.eaters_foodstuffs
247
+ assert_equal dependent_rows.length, @kibbles.eaters.count
248
+ @join_count = EatersFoodstuff.count
249
+
250
+ @kibbles.destroy
251
+ assert_equal @join_count - dependent_rows.length, EatersFoodstuff.count
252
+ assert_equal 0, EatersFoodstuff.find(:all, :conditions => ['foodstuff_id = ?', 1] ).length
253
+ end
254
+
255
+ def test_normal_callbacks
256
+ assert @rover.respond_to?(:after_initialize)
257
+ assert @rover.respond_to?(:after_find)
258
+ assert @rover.after_initialize_test
259
+ assert @rover.after_find_test
260
+ end
261
+
262
+ def test_model_callbacks_not_overridden_by_plugin_callbacks
263
+ assert 0, @bits.eaters.count
264
+ assert @bits.eaters.push(@rover)
265
+ @bits.save
266
+ @bits2 = Petfood.find_by_name("Bits")
267
+ @bits.reload
268
+ assert rover = @bits2.eaters.select { |x| x.name == "Rover" }[0]
269
+ assert rover.after_initialize_test
270
+ assert rover.after_find_test
271
+ end
272
+
273
+ def test_number_of_join_records
274
+ assert EatersFoodstuff.create(:foodstuff_id => 1, :eater_id => 1, :eater_type => "Cat")
275
+ @join_count = EatersFoodstuff.count
276
+ assert @join_count > 0
277
+ end
278
+
279
+ def test_number_of_regular_records
280
+ dogs = Dog.count
281
+ assert Dog.new(:name => "Auggie").save!
282
+ assert dogs + 1, Dog.count
283
+ end
284
+
285
+ def test_attributes_come_through_when_child_has_underscore_in_table_name
286
+ join = EatersFoodstuff.new(:foodstuff_id => @bits.id, :eater_id => @puma.id, :eater_type => @puma.class.name)
287
+ join.save!
288
+
289
+ @bits.eaters.reload
290
+
291
+ assert_equal "Puma", @puma.name
292
+ assert_equal "Puma", @bits.eaters.first.name
293
+ end
294
+
295
+
296
+ def test_before_save_on_join_table_is_not_clobbered_by_sti_base_class_fix
297
+ assert @kibbles.eaters << @chloe
298
+ assert_equal 3, @kibbles.eaters_foodstuffs.first.some_attribute
299
+ end
300
+
301
+ def test_sti_type_counts_are_correct
302
+ @kibbles.eaters << [@chloe, @alice, @toby]
303
+ assert_equal 2, @kibbles.eater_kittens.count
304
+ assert_equal 1, @kibbles.eater_tabbies.count
305
+ assert !@kibbles.respond_to?(:eater_cats)
306
+ end
307
+
308
+
309
+ def test_creating_namespaced_relationship
310
+ assert @shamu.aquatic_pupils.empty?
311
+ @shamu.aquatic_pupils << @swimmy
312
+ assert_equal 1, @shamu.aquatic_pupils.length
313
+ @shamu.reload
314
+ assert_equal 1, @shamu.aquatic_pupils.length
315
+ end
316
+
317
+ def test_namespaced_polymorphic_collection
318
+ @shamu.aquatic_pupils << @swimmy
319
+ assert @shamu.aquatic_pupils.any? {|obj| obj == @swimmy}
320
+ @shamu.reload
321
+ assert @shamu.aquatic_pupils.any? {|obj| obj == @swimmy}
322
+
323
+ @shamu.aquatic_pupils << @spot
324
+ assert @shamu.dogs.any? {|obj| obj == @spot}
325
+ assert @shamu.aquatic_pupils.any? {|obj| obj == @swimmy}
326
+ assert_equal @swimmy, @shamu.aquatic_fish.first
327
+ assert_equal 10, @shamu.aquatic_fish.first.speed
328
+ end
329
+
330
+ def test_deleting_namespaced_relationship
331
+ @shamu.aquatic_pupils << @swimmy
332
+ @shamu.aquatic_pupils << @spot
333
+
334
+ @shamu.reload
335
+ @shamu.aquatic_pupils.delete @spot
336
+ assert !@shamu.dogs.any? {|obj| obj == @spot}
337
+ assert !@shamu.aquatic_pupils.any? {|obj| obj == @spot}
338
+ assert_equal 1, @shamu.aquatic_pupils.length
339
+ end
340
+
341
+ def test_unrenamed_parent_of_namespaced_child
342
+ @shamu.aquatic_pupils << @swimmy
343
+ assert_equal [@shamu], @swimmy.whales
344
+ end
345
+
346
+ def test_empty_double_collections
347
+ assert @puma.enemies.empty?
348
+ assert @froggy.protectors.empty?
349
+ assert @alice.enemies.empty?
350
+ assert @spot.protectors.empty?
351
+ assert @alice.beautiful_fight_relationships_as_enemy.empty?
352
+ assert @alice.beautiful_fight_relationships_as_protector.empty?
353
+ assert @alice.beautiful_fight_relationships.empty?
354
+ end
355
+
356
+ def test_double_collection_assignment
357
+ @alice.enemies << @spot
358
+ @alice.reload
359
+ @spot.reload
360
+ assert @spot.protectors.any? {|obj| obj == @alice}
361
+ assert @alice.enemies.any? {|obj| obj == @spot}
362
+ assert !@alice.protectors.any? {|obj| obj == @alice}
363
+ assert_equal 1, @alice.beautiful_fight_relationships_as_protector.size
364
+ assert_equal 0, @alice.beautiful_fight_relationships_as_enemy.size
365
+ assert_equal 1, @alice.beautiful_fight_relationships.size
366
+
367
+ # self reference
368
+ assert_equal 1, @alice.enemies.length
369
+ @alice.enemies.push @alice
370
+ assert @alice.enemies.any? {|obj| obj == @alice}
371
+ assert_equal 2, @alice.enemies.length
372
+ @alice.reload
373
+ assert_equal 2, @alice.beautiful_fight_relationships_as_protector.size
374
+ assert_equal 1, @alice.beautiful_fight_relationships_as_enemy.size
375
+ assert_equal 3, @alice.beautiful_fight_relationships.size
376
+ end
377
+
378
+ def test_double_collection_build_join_record_on_association
379
+
380
+ join = @alice.beautiful_fight_relationships_as_protector.build(:enemy => @spot)
381
+
382
+ assert_equal @alice.class.base_class.name, join.protector_type
383
+ assert_nothing_raised { join.save! }
384
+
385
+ assert join.id
386
+ assert_equal @double_join_count + 1, BeautifulFightRelationship.count
387
+
388
+ assert @alice.enemies.reload
389
+ assert @alice.enemies.any? {|obj| obj == @spot}
390
+ end
391
+
392
+ def test_double_dependency_injection
393
+ # breakpoint
394
+ end
395
+
396
+ def test_double_collection_deletion
397
+ @alice.enemies << @spot
398
+ @alice.reload
399
+ assert @alice.enemies.any? {|obj| obj == @spot}
400
+ @alice.enemies.delete(@spot)
401
+ assert !@alice.enemies.any? {|obj| obj == @spot}
402
+ assert @alice.enemies.empty?
403
+ @alice.reload
404
+ assert !@alice.enemies.any? {|obj| obj == @spot}
405
+ assert @alice.enemies.empty?
406
+ assert_equal 0, @alice.beautiful_fight_relationships.size
407
+ end
408
+
409
+ def test_double_collection_deletion_from_opposite_side
410
+ @alice.protectors << @puma
411
+ @alice.reload
412
+ assert @alice.protectors.any? {|obj| obj == @puma}
413
+ @alice.protectors.delete(@puma)
414
+ assert !@alice.protectors.any? {|obj| obj == @puma}
415
+ assert @alice.protectors.empty?
416
+ @alice.reload
417
+ assert !@alice.protectors.any? {|obj| obj == @puma}
418
+ assert @alice.protectors.empty?
419
+ assert_equal 0, @alice.beautiful_fight_relationships.size
420
+ end
421
+
422
+ def test_individual_collections_created_for_double_relationship
423
+ assert @alice.dogs.empty?
424
+ @alice.enemies << @spot
425
+
426
+ assert @alice.enemies.any? {|obj| obj == @spot}
427
+ assert !@alice.kittens.any? {|obj| obj == @alice}
428
+
429
+ assert !@alice.dogs.any? {|obj| obj == @spot}
430
+ @alice.reload
431
+ assert @alice.dogs.any? {|obj| obj == @spot}
432
+ assert !WildBoar.find(@alice.id).dogs.any? {|obj| obj == @spot} # make sure the parent type is checked
433
+ end
434
+
435
+ def test_individual_collections_created_for_double_relationship_from_opposite_side
436
+ assert @alice.wild_boars.empty?
437
+ @alice.protectors << @puma
438
+ @alice.reload
439
+
440
+ assert @alice.protectors.any? {|obj| obj == @puma}
441
+ assert @alice.wild_boars.any? {|obj| obj == @puma}
442
+
443
+ assert !Dog.find(@alice.id).wild_boars.any? {|obj| obj == @puma} # make sure the parent type is checked
444
+ end
445
+
446
+ def test_self_referential_individual_collections_created_for_double_relationship
447
+ @alice.enemies << @alice
448
+ @alice.reload
449
+ assert @alice.enemy_kittens.any? {|obj| obj == @alice}
450
+ assert @alice.protector_kittens.any? {|obj| obj == @alice}
451
+ assert @alice.kittens.any? {|obj| obj == @alice}
452
+ assert_equal 2, @alice.kittens.size
453
+
454
+ @alice.enemies << (@chloe = Kitten.find_by_name('Chloe'))
455
+ @alice.reload
456
+ assert @alice.enemy_kittens.any? {|obj| obj == @chloe}
457
+ assert !@alice.protector_kittens.any? {|obj| obj == @chloe}
458
+ assert @alice.kittens.any? {|obj| obj == @chloe}
459
+ assert_equal 3, @alice.kittens.size
460
+ end
461
+
462
+ def test_child_of_polymorphic_join_can_reach_parent
463
+ @alice.enemies << @spot
464
+ @alice.reload
465
+ assert @spot.protectors.any? {|obj| obj == @alice}
466
+ end
467
+
468
+ def test_double_collection_deletion_from_child_polymorphic_join
469
+ @alice.enemies << @spot
470
+ @spot.protectors.delete(@alice)
471
+ assert !@spot.protectors.any? {|obj| obj == @alice}
472
+ @alice.reload
473
+ assert !@alice.enemies.any? {|obj| obj == @spot}
474
+ BeautifulFightRelationship.create(:protector_id => 2, :protector_type => "Dog", :enemy_id => @spot.id, :enemy_type => @spot.class.name)
475
+ @alice.enemies << @spot
476
+ @spot.protectors.delete(@alice)
477
+ assert !@spot.protectors.any? {|obj| obj == @alice}
478
+ end
479
+
480
+ def test_collection_query_on_unsaved_record
481
+ assert Dog.new.enemies.empty?
482
+ assert Dog.new.foodstuffs_of_eaters.empty?
483
+ end
484
+
485
+ def test_double_individual_collections_push
486
+ assert_equal [@chloe], (@spot.protector_kittens << @chloe)
487
+ @spot.reload
488
+ assert @spot.protectors.any? {|obj| obj == @chloe}
489
+ assert @spot.protector_kittens.any? {|obj| obj == @chloe}
490
+ assert !@spot.protector_dogs.any? {|obj| obj == @chloe}
491
+
492
+ assert_equal [@froggy], (@spot.frogs << @froggy)
493
+ @spot.reload
494
+ assert @spot.enemies.any? {|obj| obj == @froggy}
495
+ assert @spot.frogs.any? {|obj| obj == @froggy}
496
+ assert !@spot.enemy_dogs.any? {|obj| obj == @froggy}
497
+ end
498
+
499
+ def test_double_individual_collections_delete
500
+ @spot.protectors << [@chloe, @puma]
501
+ @spot.reload
502
+ assert_equal [@chloe], @spot.protector_kittens.delete(@chloe)
503
+ assert @spot.protector_kittens.empty?
504
+ @spot.protector_kittens.delete(@chloe) # again, unclear what .delete should return
505
+
506
+ @spot.reload
507
+ assert @spot.protector_kittens.empty?
508
+ assert @spot.wild_boars.any? {|obj| obj == @puma}
509
+ end
510
+
511
+ def test_double_individual_collections_clear
512
+ @spot.protectors << [@chloe, @puma, @alice]
513
+ @spot.reload
514
+ assert_equal [], @spot.protector_kittens.clear
515
+ assert @spot.protector_kittens.empty?
516
+ assert_equal 1, @spot.protectors.size
517
+ @spot.reload
518
+ assert @spot.protector_kittens.empty?
519
+ assert_equal 1, @spot.protectors.size
520
+ assert !@spot.protector_kittens.any? {|obj| obj == @chloe}
521
+ assert !@spot.protectors.any? {|obj| obj == @chloe}
522
+ assert !@spot.protector_kittens.any? {|obj| obj == @alice}
523
+ assert !@spot.protectors.any? {|obj| obj == @alice}
524
+ assert @spot.protectors.any? {|obj| obj == @puma}
525
+ assert @spot.wild_boars.any? {|obj| obj == @puma}
526
+ end
527
+
528
+ def test_single_extensions
529
+ assert_equal :correct_block_result, @shamu.aquatic_pupils.a_method
530
+ @kibbles.eaters.push(@alice)
531
+ @kibbles.eaters.push(@spot)
532
+ assert_equal :correct_join_result, @kibbles.eaters_foodstuffs.a_method
533
+ assert_equal :correct_module_result, @kibbles.eaters.a_method
534
+ assert_equal :correct_other_module_result, @kibbles.eaters.another_method
535
+ @kibbles.eaters.each do |eater|
536
+ assert_equal :correct_join_result, eater.eaters_foodstuffs.a_method
537
+ end
538
+ assert_equal :correct_parent_proc_result, @kibbles.foodstuffs_of_eaters.a_method
539
+ assert_equal :correct_parent_proc_result, @kibbles.eaters.first.foodstuffs_of_eaters.a_method
540
+ end
541
+
542
+ def test_double_extensions
543
+ assert_equal :correct_proc_result, @spot.protectors.a_method
544
+ assert_equal :correct_module_result, @spot.enemies.a_method
545
+ assert_equal :correct_join_result, @spot.beautiful_fight_relationships_as_enemy.a_method
546
+ assert_equal :correct_join_result, @spot.beautiful_fight_relationships_as_protector.a_method
547
+ assert_equal :correct_join_result, @froggy.beautiful_fight_relationships.a_method
548
+ assert_equal :correct_join_result, @froggy.beautiful_fight_relationships_as_enemy.a_method
549
+ assert_raises(NoMethodError) {@froggy.beautiful_fight_relationships_as_protector.a_method}
550
+ end
551
+
552
+ def test_pluralization_checks
553
+ assert_raises(@association_error) {
554
+ eval "class SomeModel < ActiveRecord::Base
555
+ has_many_polymorphs :polymorphs, :from => [:dog, :cats]
556
+ end" }
557
+ assert_raises(@association_error) {
558
+ eval "class SomeModel < ActiveRecord::Base
559
+ has_many_polymorphs :polymorph, :from => [:dogs, :cats]
560
+ end" }
561
+ assert_raises(@association_error) {
562
+ eval "class SomeModel < ActiveRecord::Base
563
+ acts_as_double_polymorphic_join :polymorph => [:dogs, :cats], :unimorphs => [:dogs, :cats]
564
+ end" }
565
+ end
566
+
567
+ def test_error_message_on_namespaced_targets
568
+ assert_raises(@association_error) {
569
+ eval "class SomeModel < ActiveRecord::Base
570
+ has_many_polymorphs :polymorphs, :from => [:fish]
571
+ end" }
572
+ end
573
+
574
+ def test_single_custom_finders
575
+ [@kibbles, @alice, @puma, @spot, @bits].each {|record| @kibbles.eaters << record; sleep 1} # XXX yeah i know
576
+ assert_equal @kibbles.eaters, @kibbles.eaters.find(:all, :order => "eaters_foodstuffs.created_at ASC")
577
+ assert_equal @kibbles.eaters.reverse, @kibbles.eaters.find(:all, :order => "eaters_foodstuffs.created_at DESC")
578
+ if (ActiveRecord::Base.connection.is_a? ActiveRecord::ConnectionAdapters::MysqlAdapter rescue false)
579
+ assert_equal @kibbles.eaters.sort_by(&:created_at), @kibbles.eaters.find(:all, :order => "IFNULL(bow_wows.created_at,(IFNULL(petfoods.created_at,(IFNULL(wild_boars.created_at,(IFNULL(cats.created_at,fish.created_at))))))) ASC")
580
+ end
581
+ assert_equal @kibbles.eaters.select{|x| x.is_a? Petfood}, @kibbles.eater_petfoods.find(:all, :order => "eaters_foodstuffs.created_at ASC")
582
+ end
583
+
584
+ def test_double_custom_finders
585
+ @spot.protectors << [@chloe, @puma, @alice]
586
+ assert_equal [@chloe], @spot.protectors.find(:all, :conditions => ["cats.name = ?", @chloe.name], :limit => 1)
587
+ assert_equal [], @spot.protectors.find(:all, :conditions => ["cats.name = ?", @chloe.name], :limit => 1, :offset => 1)
588
+ assert_equal 2, @spot.protectors.find(:all, :limit => 100, :offset => 1).size
589
+ end
590
+
591
+ def test_single_custom_finder_parameters_carry_to_individual_relationships
592
+ # XXX test nullout here
593
+ end
594
+
595
+ def test_double_custom_finder_parameters_carry_to_individual_relationships
596
+ # XXX test nullout here
597
+ end
598
+
599
+ def test_include_doesnt_fail
600
+ assert_nothing_raised do
601
+ @spot.protectors.find(:all, :include => :wild_boars)
602
+ end
603
+ end
604
+
605
+ def test_abstract_method
606
+ assert_equal :correct_abstract_method_response, @spot.an_abstract_method
607
+ end
608
+
609
+ def test_missing_target_should_raise
610
+ @kibbles.eaters << [@kibbles, @alice, @puma, @spot, @bits]
611
+ @spot.destroy_without_callbacks
612
+ assert_raises(@association_error) { @kibbles.eaters.reload }
613
+ # assert_raises(@association_error) { @kibbles.eater_dogs.reload } # bah AR
614
+ end
615
+
616
+ def test_lazy_loading_is_lazy
617
+ # XXX
618
+ end
619
+
620
+ def test_push_with_skip_duplicates_false_doesnt_load_target
621
+ # Loading kibbles locally again because setup calls .size which loads target
622
+ kibbles = Petfood.find(1)
623
+ assert !kibbles.eaters.loaded?
624
+ assert !(kibbles.eater_dogs << Dog.create!(:name => "Mongy")).loaded?
625
+ assert !kibbles.eaters.loaded?
626
+ end
627
+
628
+ def test_association_foreign_key_is_sane
629
+ assert_equal "eater_id", Petfood.reflect_on_association(:eaters).association_foreign_key
630
+ end
631
+
632
+ def test_reflection_instance_methods_are_sane
633
+ assert_equal EatersFoodstuff, Petfood.reflect_on_association(:eaters).klass
634
+ assert_equal EatersFoodstuff.name, Petfood.reflect_on_association(:eaters).class_name
635
+ end
636
+
637
+ def test_parent_order
638
+ @alice.foodstuffs_of_eaters << Petfood.find(:all, :order => "the_petfood_primary_key ASC")
639
+ @alice.reload #not necessary
640
+ assert_equal [2,1], @alice.foodstuffs_of_eaters.map(&:id)
641
+ end
642
+
643
+ def test_parent_conditions
644
+ @kibbles.eaters << @alice
645
+ assert_equal [@alice], @kibbles.eaters
646
+
647
+ @snausages = Petfood.create(:name => 'Snausages')
648
+ @snausages.eaters << @alice
649
+ assert_equal [@alice], @snausages.eaters
650
+
651
+ assert_equal [@kibbles], @alice.foodstuffs_of_eaters
652
+ end
653
+
654
+ def test_self_referential_hmp_with_conditions
655
+ p = Person.find(:first)
656
+ kid = Person.create(:name => "Tim", :age => 3)
657
+ p.kids << kid
658
+
659
+ kid.reload; p.reload
660
+
661
+ # assert_equal [p], kid.parents
662
+ # assert Rails.has_one? Bug
663
+ # non-standard foreign_type key is not set properly when you are the polymorphic interface of a has_many going to a :through
664
+
665
+ assert_equal [kid], p.kids
666
+ assert_equal [kid], p.people
667
+ end
668
+
669
+ # def test_polymorphic_include
670
+ # @kibbles.eaters << [@kibbles, @alice, @puma, @spot, @bits]
671
+ # assert @kibbles.eaters.include?(@kibbles.eaters_foodstuffs.find(:all, :include => :eater).first.eater)
672
+ # end
673
+ #
674
+ # def test_double_polymorphic_include
675
+ # end
676
+ #
677
+ # def test_single_child_include
678
+ # end
679
+ #
680
+ # def test_double_child_include
681
+ # end
682
+ #
683
+ # def test_single_include_from_parent
684
+ # end
685
+ #
686
+ # def test_double_include_from_parent
687
+ # end
688
+ #
689
+ # def test_meta_referential_single_include
690
+ # end
691
+ #
692
+ # def test_meta_referential_double_include
693
+ # end
694
+ #
695
+ # def test_meta_referential_single_include
696
+ # end
697
+ #
698
+ # def test_meta_referential_single_double_multi_include
699
+ # end
700
+ #
701
+ # def test_dont_ignore_duplicates
702
+ # end
703
+ #
704
+ # def test_ignore_duplicates
705
+ # end
706
+ #
707
+ # def test_tagging_system_generator
708
+ # end
709
+ #
710
+ # def test_tagging_system_library
711
+ # end
712
+
713
+ end