ibm_db 2.5.26-universal-darwin-14 → 2.6.1-universal-darwin-14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +11 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +264 -261
  8. data/ext/extconf_MacOS.rb +269 -0
  9. data/ext/ibm_db.c +11879 -11793
  10. data/ext/ruby_ibm_db.h +241 -240
  11. data/ext/ruby_ibm_db_cli.c +851 -845
  12. data/ext/ruby_ibm_db_cli.h +500 -489
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -19
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3339 -3289
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/test/cases/adapter_test.rb +207 -207
  19. data/test/cases/associations/belongs_to_associations_test.rb +711 -711
  20. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
  21. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
  22. data/test/cases/associations/join_model_test.rb +743 -743
  23. data/test/cases/attribute_methods_test.rb +822 -822
  24. data/test/cases/base_test.rb +2133 -2133
  25. data/test/cases/calculations_test.rb +482 -482
  26. data/test/cases/migration_test.rb +2408 -2408
  27. data/test/cases/persistence_test.rb +642 -642
  28. data/test/cases/query_cache_test.rb +257 -257
  29. data/test/cases/relations_test.rb +1182 -1182
  30. data/test/cases/schema_dumper_test.rb +256 -256
  31. data/test/cases/transaction_callbacks_test.rb +300 -300
  32. data/test/cases/validations/uniqueness_validation_test.rb +299 -299
  33. data/test/cases/xml_serialization_test.rb +408 -408
  34. data/test/config.yml +154 -154
  35. data/test/connections/native_ibm_db/connection.rb +43 -43
  36. data/test/ibm_db_test.rb +24 -24
  37. data/test/models/warehouse_thing.rb +4 -4
  38. data/test/schema/schema.rb +751 -751
  39. metadata +6 -8
  40. data/lib/linux/rb18x/ibm_db.bundle +0 -0
  41. data/lib/linux/rb19x/ibm_db.bundle +0 -0
  42. data/lib/linux/rb20x/ibm_db.bundle +0 -0
  43. data/lib/linux/rb21x/ibm_db.bundle +0 -0
@@ -1,743 +1,743 @@
1
- require "cases/helper"
2
- require 'active_support/core_ext/object/inclusion'
3
- require 'models/tag'
4
- require 'models/tagging'
5
- require 'models/post'
6
- require 'models/rating'
7
- require 'models/item'
8
- require 'models/comment'
9
- require 'models/author'
10
- require 'models/category'
11
- require 'models/categorization'
12
- require 'models/vertex'
13
- require 'models/edge'
14
- require 'models/book'
15
- require 'models/citation'
16
- require 'models/aircraft'
17
- require 'models/engine'
18
- require 'models/car'
19
-
20
- class AssociationsJoinModelTest < ActiveRecord::TestCase
21
- self.use_transactional_fixtures = false unless supports_savepoints?
22
-
23
- fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books,
24
- # Reload edges table from fixtures as otherwise repeated test was failing
25
- :edges
26
-
27
- def test_has_many
28
- assert authors(:david).categories.include?(categories(:general))
29
- end
30
-
31
- def test_has_many_inherited
32
- assert authors(:mary).categories.include?(categories(:sti_test))
33
- end
34
-
35
- def test_inherited_has_many
36
- assert categories(:sti_test).authors.include?(authors(:mary))
37
- end
38
-
39
- def test_has_many_uniq_through_join_model
40
- assert_equal 2, authors(:mary).categorized_posts.size
41
- assert_equal 1, authors(:mary).unique_categorized_posts.size
42
- end
43
-
44
- def test_has_many_uniq_through_count
45
- author = authors(:mary)
46
- assert !authors(:mary).unique_categorized_posts.loaded?
47
- assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
48
- assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
49
- assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
50
- assert !authors(:mary).unique_categorized_posts.loaded?
51
- end
52
-
53
- def test_has_many_uniq_through_find
54
- assert_equal 1, authors(:mary).unique_categorized_posts.find(:all).size
55
- end
56
-
57
- def test_has_many_uniq_through_dynamic_find
58
- assert_equal 1, authors(:mary).unique_categorized_posts.find_all_by_title("So I was thinking").size
59
- end
60
-
61
- def test_polymorphic_has_many_going_through_join_model
62
- assert_equal tags(:general), tag = posts(:welcome).tags.first
63
- assert_no_queries do
64
- tag.tagging
65
- end
66
- end
67
-
68
- def test_count_polymorphic_has_many
69
- assert_equal 1, posts(:welcome).taggings.count
70
- assert_equal 1, posts(:welcome).tags.count
71
- end
72
-
73
- def test_polymorphic_has_many_going_through_join_model_with_find
74
- assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
75
- assert_no_queries do
76
- tag.tagging
77
- end
78
- end
79
-
80
- def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
81
- assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
82
- assert_no_queries do
83
- tag.tagging
84
- end
85
- end
86
-
87
- def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
88
- assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
89
- assert_no_queries do
90
- tag.tagging
91
- end
92
- end
93
-
94
- def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
95
- assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
96
- assert_nothing_raised(NoMethodError) { tag.author_id }
97
- end
98
-
99
- def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
100
- assert_equal tags(:misc), taggings(:welcome_general).super_tag
101
- assert_equal tags(:misc), posts(:welcome).super_tags.first
102
- end
103
-
104
- def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
105
- post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
106
- assert_instance_of SubStiPost, post
107
-
108
- tagging = tags(:misc).taggings.create(:taggable => post)
109
- assert_equal "SubStiPost", tagging.taggable_type
110
- end
111
-
112
- def test_polymorphic_has_many_going_through_join_model_with_inheritance
113
- assert_equal tags(:general), posts(:thinking).tags.first
114
- end
115
-
116
- def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
117
- assert_equal tags(:general), posts(:thinking).funky_tags.first
118
- end
119
-
120
- def test_polymorphic_has_many_create_model_with_inheritance
121
- post = posts(:thinking)
122
- assert_instance_of SpecialPost, post
123
-
124
- tagging = tags(:misc).taggings.create(:taggable => post)
125
- assert_equal "Post", tagging.taggable_type
126
- end
127
-
128
- def test_polymorphic_has_one_create_model_with_inheritance
129
- tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
130
- assert_equal "Post", tagging.taggable_type
131
- end
132
-
133
- def test_set_polymorphic_has_many
134
- tagging = tags(:misc).taggings.create
135
- posts(:thinking).taggings << tagging
136
- assert_equal "Post", tagging.taggable_type
137
- end
138
-
139
- def test_set_polymorphic_has_one
140
- tagging = tags(:misc).taggings.create
141
- posts(:thinking).tagging = tagging
142
-
143
- assert_equal "Post", tagging.taggable_type
144
- assert_equal posts(:thinking).id, tagging.taggable_id
145
- assert_equal posts(:thinking), tagging.taggable
146
- end
147
-
148
- def test_set_polymorphic_has_one_on_new_record
149
- tagging = tags(:misc).taggings.create
150
- post = Post.new :title => "foo", :body => "bar"
151
- post.tagging = tagging
152
- post.save!
153
-
154
- assert_equal "Post", tagging.taggable_type
155
- assert_equal post.id, tagging.taggable_id
156
- assert_equal post, tagging.taggable
157
- end
158
-
159
- def test_create_polymorphic_has_many_with_scope
160
- old_count = posts(:welcome).taggings.count
161
- tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
162
- assert_equal "Post", tagging.taggable_type
163
- assert_equal old_count+1, posts(:welcome).taggings.count
164
- end
165
-
166
- def test_create_bang_polymorphic_with_has_many_scope
167
- old_count = posts(:welcome).taggings.count
168
- tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
169
- assert_equal "Post", tagging.taggable_type
170
- assert_equal old_count+1, posts(:welcome).taggings.count
171
- end
172
-
173
- def test_create_polymorphic_has_one_with_scope
174
- old_count = Tagging.count
175
- tagging = posts(:welcome).create_tagging(:tag => tags(:misc))
176
- assert_equal "Post", tagging.taggable_type
177
- assert_equal old_count+1, Tagging.count
178
- end
179
-
180
- def test_delete_polymorphic_has_many_with_delete_all
181
- assert_equal 1, posts(:welcome).taggings.count
182
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDeleteAll'
183
- post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
184
-
185
- old_count = Tagging.count
186
- post.destroy
187
- assert_equal old_count-1, Tagging.count
188
- assert_equal 0, posts(:welcome).taggings.count
189
- end
190
-
191
- def test_delete_polymorphic_has_many_with_destroy
192
- assert_equal 1, posts(:welcome).taggings.count
193
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDestroy'
194
- post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
195
-
196
- old_count = Tagging.count
197
- post.destroy
198
- assert_equal old_count-1, Tagging.count
199
- assert_equal 0, posts(:welcome).taggings.count
200
- end
201
-
202
- def test_delete_polymorphic_has_many_with_nullify
203
- assert_equal 1, posts(:welcome).taggings.count
204
- posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyNullify'
205
- post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
206
-
207
- old_count = Tagging.count
208
- post.destroy
209
- assert_equal old_count, Tagging.count
210
- assert_equal 0, posts(:welcome).taggings.count
211
- end
212
-
213
- def test_delete_polymorphic_has_one_with_destroy
214
- assert posts(:welcome).tagging
215
- posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneDestroy'
216
- post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
217
-
218
- old_count = Tagging.count
219
- post.destroy
220
- assert_equal old_count-1, Tagging.count
221
- assert_nil posts(:welcome).tagging(true)
222
- end
223
-
224
- def test_delete_polymorphic_has_one_with_nullify
225
- assert posts(:welcome).tagging
226
- posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneNullify'
227
- post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
228
-
229
- old_count = Tagging.count
230
- post.destroy
231
- assert_equal old_count, Tagging.count
232
- assert_nil posts(:welcome).tagging(true)
233
- end
234
-
235
- def test_has_many_with_piggyback
236
- assert_equal "2", categories(:sti_test).authors_with_select.first.post_id.to_s
237
- end
238
-
239
- def test_include_has_many_through
240
- posts = Post.find(:all, :order => 'posts.id')
241
- posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
242
- assert_equal posts.length, posts_with_authors.length
243
- posts.length.times do |i|
244
- assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
245
- end
246
- end
247
-
248
- def test_include_polymorphic_has_one
249
- post = Post.find_by_id(posts(:welcome).id, :include => :tagging)
250
- tagging = taggings(:welcome_general)
251
- assert_no_queries do
252
- assert_equal tagging, post.tagging
253
- end
254
- end
255
-
256
- def test_include_polymorphic_has_one_defined_in_abstract_parent
257
- item = Item.find_by_id(items(:dvd).id, :include => :tagging)
258
- tagging = taggings(:godfather)
259
- assert_no_queries do
260
- assert_equal tagging, item.tagging
261
- end
262
- end
263
-
264
- def test_include_polymorphic_has_many_through
265
- posts = Post.find(:all, :order => 'posts.id')
266
- posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
267
- assert_equal posts.length, posts_with_tags.length
268
- posts.length.times do |i|
269
- assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
270
- end
271
- end
272
-
273
- def test_include_polymorphic_has_many
274
- posts = Post.find(:all, :order => 'posts.id')
275
- posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
276
- assert_equal posts.length, posts_with_taggings.length
277
- posts.length.times do |i|
278
- assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
279
- end
280
- end
281
-
282
- def test_has_many_find_all
283
- assert_equal [categories(:general)], authors(:david).categories.find(:all)
284
- end
285
-
286
- def test_has_many_find_first
287
- assert_equal categories(:general), authors(:david).categories.find(:first)
288
- end
289
-
290
- def test_has_many_with_hash_conditions
291
- assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
292
- end
293
-
294
- def test_has_many_find_conditions
295
- assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
296
- assert_nil authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
297
- end
298
-
299
- def test_has_many_class_methods_called_by_method_missing
300
- assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
301
- assert_nil authors(:david).categories.find_by_name('Technology')
302
- end
303
-
304
- def test_has_many_array_methods_called_by_method_missing
305
- assert authors(:david).categories.any? { |category| category.name == 'General' }
306
- assert_nothing_raised { authors(:david).categories.sort }
307
- end
308
-
309
- def test_has_many_going_through_join_model_with_custom_foreign_key
310
- assert_equal [authors(:bob)], posts(:thinking).authors
311
- assert_equal [authors(:mary)], posts(:authorless).authors
312
- end
313
-
314
- def test_has_many_going_through_join_model_with_custom_primary_key
315
- assert_equal [authors(:david)], posts(:thinking).authors_using_author_id
316
- end
317
-
318
- def test_has_many_going_through_polymorphic_join_model_with_custom_primary_key
319
- assert_equal [tags(:general)], posts(:eager_other).tags_using_author_id
320
- end
321
-
322
- def test_has_many_through_with_custom_primary_key_on_belongs_to_source
323
- assert_equal [authors(:david), authors(:david)], posts(:thinking).author_using_custom_pk
324
- end
325
-
326
- def test_has_many_through_with_custom_primary_key_on_has_many_source
327
- assert_equal [authors(:david), authors(:bob)], posts(:thinking).authors_using_custom_pk.order('authors.id')
328
- end
329
-
330
- def test_both_scoped_and_explicit_joins_should_be_respected
331
- assert_nothing_raised do
332
- Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
333
- Post.find :all, :select => "comments.id, authors.id", :joins => "left outer join authors on authors.id = posts.author_id"
334
- end
335
- end
336
- end
337
-
338
- def test_belongs_to_polymorphic_with_counter_cache
339
- assert_equal 1, posts(:welcome)[:taggings_count]
340
- tagging = posts(:welcome).taggings.create(:tag => tags(:general))
341
- assert_equal 2, posts(:welcome, :reload)[:taggings_count]
342
- tagging.destroy
343
- assert_equal 1, posts(:welcome, :reload)[:taggings_count]
344
- end
345
-
346
- def test_unavailable_through_reflection
347
- assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
348
- end
349
-
350
- def test_has_many_through_join_model_with_conditions
351
- assert_equal [], posts(:welcome).invalid_taggings
352
- assert_equal [], posts(:welcome).invalid_tags
353
- end
354
-
355
- def test_has_many_polymorphic
356
- assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicSourceError do
357
- tags(:general).taggables
358
- end
359
-
360
- assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicThroughError do
361
- taggings(:welcome_general).things
362
- end
363
-
364
- assert_raise ActiveRecord::EagerLoadPolymorphicError do
365
- tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
366
- end
367
- end
368
-
369
- def test_has_many_polymorphic_with_source_type
370
- # added sort by ID as otherwise Oracle select sometimes returned rows in different order
371
- assert_equal posts(:welcome, :thinking).sort_by(&:id), tags(:general).tagged_posts.sort_by(&:id)
372
- end
373
-
374
- def test_eager_has_many_polymorphic_with_source_type
375
- tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
376
- desired = posts(:welcome, :thinking)
377
- assert_no_queries do
378
- # added sort by ID as otherwise test using JRuby was failing as array elements were in different order
379
- assert_equal desired.sort_by(&:id), tag_with_include.tagged_posts.sort_by(&:id)
380
- end
381
- assert_equal 5, tag_with_include.taggings.length
382
- end
383
-
384
- def test_has_many_through_has_many_find_all
385
- assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
386
- end
387
-
388
- def test_has_many_through_has_many_find_all_with_custom_class
389
- assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
390
- end
391
-
392
- def test_has_many_through_has_many_find_first
393
- assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
394
- end
395
-
396
- def test_has_many_through_has_many_find_conditions
397
- options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
398
- assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
399
- end
400
-
401
- def test_has_many_through_has_many_find_by_id
402
- assert_equal comments(:more_greetings), authors(:david).comments.find(2)
403
- end
404
-
405
- def test_has_many_through_polymorphic_has_one
406
- assert_equal Tagging.find(1,2).sort_by { |t| t.id }, authors(:david).tagging.order(:id)
407
- end
408
-
409
- def test_has_many_through_polymorphic_has_many
410
- assert_equal taggings(:welcome_general, :thinking_general), authors(:david).taggings.uniq.sort_by { |t| t.id }
411
- end
412
-
413
- def test_include_has_many_through_polymorphic_has_many
414
- author = Author.find_by_id(authors(:david).id, :include => :taggings)
415
- expected_taggings = taggings(:welcome_general, :thinking_general)
416
- assert_no_queries do
417
- assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
418
- end
419
- end
420
-
421
- unless current_adapter?(:IBM_DBAdapter)
422
- # DB2 throws SQL0214N
423
- def test_eager_load_has_many_through_has_many
424
- author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
425
- SpecialComment.new; VerySpecialComment.new
426
- assert_no_queries do
427
- assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id)
428
- end
429
- end
430
- end
431
-
432
- def test_eager_load_has_many_through_has_many_with_conditions
433
- post = Post.find(:first, :include => :invalid_tags)
434
- assert_no_queries do
435
- post.invalid_tags
436
- end
437
- end
438
-
439
- def test_eager_belongs_to_and_has_one_not_singularized
440
- assert_nothing_raised do
441
- Author.find(:first, :include => :author_address)
442
- AuthorAddress.find(:first, :include => :author)
443
- end
444
- end
445
-
446
- def test_self_referential_has_many_through
447
- assert_equal [authors(:mary)], authors(:david).favorite_authors
448
- assert_equal [], authors(:mary).favorite_authors
449
- end
450
-
451
- def test_add_to_self_referential_has_many_through
452
- new_author = Author.create(:name => "Bob")
453
- authors(:david).author_favorites.create :favorite_author => new_author
454
- assert_equal new_author, authors(:david).reload.favorite_authors.first
455
- end
456
-
457
- def test_has_many_through_uses_conditions_specified_on_the_has_many_association
458
- author = Author.order(:id).first
459
- assert_present author.comments
460
- assert_blank author.nonexistant_comments
461
- end
462
-
463
- def test_has_many_through_uses_correct_attributes
464
- assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
465
- end
466
-
467
- def test_associating_unsaved_records_with_has_many_through
468
- saved_post = posts(:thinking)
469
- new_tag = Tag.new(:name => "new")
470
-
471
- saved_post.tags << new_tag
472
- assert new_tag.persisted? #consistent with habtm!
473
- assert saved_post.persisted?
474
- assert saved_post.tags.include?(new_tag)
475
-
476
- assert new_tag.persisted?
477
- assert new_tag.in?(saved_post.reload.tags(true))
478
-
479
-
480
- new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.")
481
- saved_tag = tags(:general)
482
-
483
- new_post.tags << saved_tag
484
- assert !new_post.persisted?
485
- assert saved_tag.persisted?
486
- assert new_post.tags.include?(saved_tag)
487
-
488
- new_post.save!
489
- assert new_post.persisted?
490
- assert saved_tag.in?(new_post.reload.tags(true))
491
-
492
- assert !posts(:thinking).tags.build.persisted?
493
- assert !posts(:thinking).tags.new.persisted?
494
- end
495
-
496
- def test_create_associate_when_adding_to_has_many_through
497
- count = posts(:thinking).tags.count
498
- push = Tag.create!(:name => 'pushme')
499
- post_thinking = posts(:thinking)
500
- assert_nothing_raised { post_thinking.tags << push }
501
- assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
502
- message = "Expected a Tag in tags collection, got #{wrong.class}.")
503
- assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
504
- message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
505
- assert_equal(count + 1, post_thinking.tags.size)
506
- assert_equal(count + 1, post_thinking.tags(true).size)
507
-
508
- assert_kind_of Tag, post_thinking.tags.create!(:name => 'foo')
509
- assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
510
- message = "Expected a Tag in tags collection, got #{wrong.class}.")
511
- assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
512
- message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
513
- assert_equal(count + 2, post_thinking.tags.size)
514
- assert_equal(count + 2, post_thinking.tags(true).size)
515
-
516
- assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
517
- assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
518
- message = "Expected a Tag in tags collection, got #{wrong.class}.")
519
- assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
520
- message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
521
- assert_equal(count + 4, post_thinking.tags.size)
522
- assert_equal(count + 4, post_thinking.tags(true).size)
523
-
524
- # Raises if the wrong reflection name is used to set the Edge belongs_to
525
- assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
526
- end
527
-
528
- def test_add_to_join_table_with_no_id
529
- assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
530
- end
531
-
532
- def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
533
- author = authors(:david)
534
- assert_equal 10, author.comments.size
535
- assert !author.comments.loaded?
536
- end
537
-
538
- def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
539
- c = categories(:general)
540
- c.categorizations_count = 100
541
- assert_equal 100, c.categorizations.size
542
- assert !c.categorizations.loaded?
543
- end
544
-
545
- def test_adding_junk_to_has_many_through_should_raise_type_mismatch
546
- assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
547
- end
548
-
549
- def test_adding_to_has_many_through_should_return_self
550
- tags = posts(:thinking).tags
551
- assert_equal tags, posts(:thinking).tags.push(tags(:general))
552
- end
553
-
554
- def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_id
555
- count = books(:awdr).references.count
556
- references_before = books(:awdr).references
557
- book = Book.create!(:name => 'Getting Real')
558
- book_awdr = books(:awdr)
559
- book_awdr.references << book
560
- assert_equal(count + 1, book_awdr.references(true).size)
561
-
562
- assert_nothing_raised { book_awdr.references.delete(book) }
563
- assert_equal(count, book_awdr.references.size)
564
- assert_equal(count, book_awdr.references(true).size)
565
- assert_equal(references_before.sort, book_awdr.references.sort)
566
- end
567
-
568
- def test_delete_associate_when_deleting_from_has_many_through
569
- count = posts(:thinking).tags.count
570
- tags_before = posts(:thinking).tags
571
- tag = Tag.create!(:name => 'doomed')
572
- post_thinking = posts(:thinking)
573
- post_thinking.tags << tag
574
- assert_equal(count + 1, post_thinking.taggings(true).size)
575
- assert_equal(count + 1, post_thinking.tags(true).size)
576
-
577
- assert_nothing_raised { post_thinking.tags.delete(tag) }
578
- assert_equal(count, post_thinking.tags.size)
579
- assert_equal(count, post_thinking.tags(true).size)
580
- assert_equal(count, post_thinking.taggings(true).size)
581
- assert_equal(tags_before.sort, post_thinking.tags.sort)
582
- end
583
-
584
- def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
585
- count = posts(:thinking).tags.count
586
- tags_before = posts(:thinking).tags
587
- doomed = Tag.create!(:name => 'doomed')
588
- doomed2 = Tag.create!(:name => 'doomed2')
589
- quaked = Tag.create!(:name => 'quaked')
590
- post_thinking = posts(:thinking)
591
- post_thinking.tags << doomed << doomed2
592
- assert_equal(count + 2, post_thinking.tags(true).size)
593
-
594
- assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
595
- assert_equal(count, post_thinking.tags.size)
596
- assert_equal(count, post_thinking.tags(true).size)
597
- assert_equal(tags_before.sort, post_thinking.tags.sort)
598
- end
599
-
600
- def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
601
- assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
602
- end
603
-
604
- def test_has_many_through_sum_uses_calculations
605
- assert_nothing_raised { authors(:david).comments.sum(:post_id) }
606
- end
607
-
608
- def test_calculations_on_has_many_through_should_disambiguate_fields
609
- assert_nothing_raised { authors(:david).categories.maximum(:id) }
610
- end
611
-
612
- def test_calculations_on_has_many_through_should_not_disambiguate_fields_unless_necessary
613
- assert_nothing_raised { authors(:david).categories.maximum("categories.id") }
614
- end
615
-
616
- def test_has_many_through_has_many_with_sti
617
- assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
618
- end
619
-
620
- def test_uniq_has_many_through_should_retain_order
621
- comment_ids = authors(:david).comments.map(&:id)
622
- assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
623
- assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
624
- end
625
-
626
- def test_polymorphic_has_many
627
- expected = taggings(:welcome_general)
628
- p = Post.find(posts(:welcome).id, :include => :taggings)
629
- assert_no_queries {assert p.taggings.include?(expected)}
630
- assert posts(:welcome).taggings.include?(taggings(:welcome_general))
631
- end
632
-
633
- def test_polymorphic_has_one
634
- expected = posts(:welcome)
635
-
636
- tagging = Tagging.find(taggings(:welcome_general).id, :include => :taggable)
637
- assert_no_queries { assert_equal expected, tagging.taggable}
638
- end
639
-
640
- def test_polymorphic_belongs_to
641
- p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable})
642
- assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable}
643
- end
644
-
645
- def test_preload_polymorphic_has_many_through
646
- posts = Post.find(:all, :order => 'posts.id')
647
- posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
648
- assert_equal posts.length, posts_with_tags.length
649
- posts.length.times do |i|
650
- assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
651
- end
652
- end
653
-
654
- def test_preload_polymorph_many_types
655
- taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel'], :order => 'id'
656
- assert_no_queries do
657
- taggings.first.taggable.id
658
- taggings[1].taggable.id
659
- end
660
-
661
- taggables = taggings.map(&:taggable)
662
- assert taggables.include?(items(:dvd))
663
- assert taggables.include?(posts(:welcome))
664
- end
665
-
666
- def test_preload_nil_polymorphic_belongs_to
667
- assert_nothing_raised do
668
- Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
669
- end
670
- end
671
-
672
- def test_preload_polymorphic_has_many
673
- posts = Post.find(:all, :order => 'posts.id')
674
- posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
675
- assert_equal posts.length, posts_with_taggings.length
676
- posts.length.times do |i|
677
- assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
678
- end
679
- end
680
-
681
- def test_belongs_to_shared_parent
682
- comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1')
683
- assert_no_queries do
684
- assert_equal comments.first.post, comments[1].post
685
- end
686
- end
687
-
688
- def test_has_many_through_include_uses_array_include_after_loaded
689
- david = authors(:david)
690
- david.categories.class # force load target
691
-
692
- category = david.categories.first
693
-
694
- assert_no_queries do
695
- assert david.categories.loaded?
696
- assert david.categories.include?(category)
697
- end
698
- end
699
-
700
- def test_has_many_through_include_checks_if_record_exists_if_target_not_loaded
701
- david = authors(:david)
702
- category = david.categories.first
703
-
704
- david.reload
705
- assert ! david.categories.loaded?
706
- assert_queries(1) do
707
- assert david.categories.include?(category)
708
- end
709
- assert ! david.categories.loaded?
710
- end
711
-
712
- def test_has_many_through_include_returns_false_for_non_matching_record_to_verify_scoping
713
- david = authors(:david)
714
- category = Category.create!(:name => 'Not Associated')
715
-
716
- assert ! david.categories.loaded?
717
- assert ! david.categories.include?(category)
718
- end
719
-
720
- def test_has_many_through_goes_through_all_sti_classes
721
- sub_sti_post = SubStiPost.create!(:title => 'test', :body => 'test', :author_id => 1)
722
- new_comment = sub_sti_post.comments.create(:body => 'test')
723
-
724
- assert_equal [9, 10, new_comment.id], authors(:david).sti_post_comments.map(&:id).sort
725
- end
726
-
727
- def test_has_many_with_pluralize_table_names_false
728
- aircraft = Aircraft.create!(:name => "Airbus 380")
729
- engine = Engine.create!(:car_id => aircraft.id)
730
- assert_equal aircraft.engines, [engine]
731
- end
732
-
733
- private
734
- # create dynamic Post models to allow different dependency options
735
- def find_post_with_dependency(post_id, association, association_name, dependency)
736
- class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
737
- Post.find(post_id).update_column :type, class_name
738
- klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
739
- klass.table_name = 'posts'
740
- klass.send(association, association_name, :as => :taggable, :dependent => dependency)
741
- klass.find(post_id)
742
- end
743
- end
1
+ require "cases/helper"
2
+ require 'active_support/core_ext/object/inclusion'
3
+ require 'models/tag'
4
+ require 'models/tagging'
5
+ require 'models/post'
6
+ require 'models/rating'
7
+ require 'models/item'
8
+ require 'models/comment'
9
+ require 'models/author'
10
+ require 'models/category'
11
+ require 'models/categorization'
12
+ require 'models/vertex'
13
+ require 'models/edge'
14
+ require 'models/book'
15
+ require 'models/citation'
16
+ require 'models/aircraft'
17
+ require 'models/engine'
18
+ require 'models/car'
19
+
20
+ class AssociationsJoinModelTest < ActiveRecord::TestCase
21
+ self.use_transactional_fixtures = false unless supports_savepoints?
22
+
23
+ fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books,
24
+ # Reload edges table from fixtures as otherwise repeated test was failing
25
+ :edges
26
+
27
+ def test_has_many
28
+ assert authors(:david).categories.include?(categories(:general))
29
+ end
30
+
31
+ def test_has_many_inherited
32
+ assert authors(:mary).categories.include?(categories(:sti_test))
33
+ end
34
+
35
+ def test_inherited_has_many
36
+ assert categories(:sti_test).authors.include?(authors(:mary))
37
+ end
38
+
39
+ def test_has_many_uniq_through_join_model
40
+ assert_equal 2, authors(:mary).categorized_posts.size
41
+ assert_equal 1, authors(:mary).unique_categorized_posts.size
42
+ end
43
+
44
+ def test_has_many_uniq_through_count
45
+ author = authors(:mary)
46
+ assert !authors(:mary).unique_categorized_posts.loaded?
47
+ assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
48
+ assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
49
+ assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
50
+ assert !authors(:mary).unique_categorized_posts.loaded?
51
+ end
52
+
53
+ def test_has_many_uniq_through_find
54
+ assert_equal 1, authors(:mary).unique_categorized_posts.find(:all).size
55
+ end
56
+
57
+ def test_has_many_uniq_through_dynamic_find
58
+ assert_equal 1, authors(:mary).unique_categorized_posts.find_all_by_title("So I was thinking").size
59
+ end
60
+
61
+ def test_polymorphic_has_many_going_through_join_model
62
+ assert_equal tags(:general), tag = posts(:welcome).tags.first
63
+ assert_no_queries do
64
+ tag.tagging
65
+ end
66
+ end
67
+
68
+ def test_count_polymorphic_has_many
69
+ assert_equal 1, posts(:welcome).taggings.count
70
+ assert_equal 1, posts(:welcome).tags.count
71
+ end
72
+
73
+ def test_polymorphic_has_many_going_through_join_model_with_find
74
+ assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
75
+ assert_no_queries do
76
+ tag.tagging
77
+ end
78
+ end
79
+
80
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
81
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
82
+ assert_no_queries do
83
+ tag.tagging
84
+ end
85
+ end
86
+
87
+ def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
88
+ assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
89
+ assert_no_queries do
90
+ tag.tagging
91
+ end
92
+ end
93
+
94
+ def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
95
+ assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
96
+ assert_nothing_raised(NoMethodError) { tag.author_id }
97
+ end
98
+
99
+ def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
100
+ assert_equal tags(:misc), taggings(:welcome_general).super_tag
101
+ assert_equal tags(:misc), posts(:welcome).super_tags.first
102
+ end
103
+
104
+ def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
105
+ post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
106
+ assert_instance_of SubStiPost, post
107
+
108
+ tagging = tags(:misc).taggings.create(:taggable => post)
109
+ assert_equal "SubStiPost", tagging.taggable_type
110
+ end
111
+
112
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance
113
+ assert_equal tags(:general), posts(:thinking).tags.first
114
+ end
115
+
116
+ def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
117
+ assert_equal tags(:general), posts(:thinking).funky_tags.first
118
+ end
119
+
120
+ def test_polymorphic_has_many_create_model_with_inheritance
121
+ post = posts(:thinking)
122
+ assert_instance_of SpecialPost, post
123
+
124
+ tagging = tags(:misc).taggings.create(:taggable => post)
125
+ assert_equal "Post", tagging.taggable_type
126
+ end
127
+
128
+ def test_polymorphic_has_one_create_model_with_inheritance
129
+ tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
130
+ assert_equal "Post", tagging.taggable_type
131
+ end
132
+
133
+ def test_set_polymorphic_has_many
134
+ tagging = tags(:misc).taggings.create
135
+ posts(:thinking).taggings << tagging
136
+ assert_equal "Post", tagging.taggable_type
137
+ end
138
+
139
+ def test_set_polymorphic_has_one
140
+ tagging = tags(:misc).taggings.create
141
+ posts(:thinking).tagging = tagging
142
+
143
+ assert_equal "Post", tagging.taggable_type
144
+ assert_equal posts(:thinking).id, tagging.taggable_id
145
+ assert_equal posts(:thinking), tagging.taggable
146
+ end
147
+
148
+ def test_set_polymorphic_has_one_on_new_record
149
+ tagging = tags(:misc).taggings.create
150
+ post = Post.new :title => "foo", :body => "bar"
151
+ post.tagging = tagging
152
+ post.save!
153
+
154
+ assert_equal "Post", tagging.taggable_type
155
+ assert_equal post.id, tagging.taggable_id
156
+ assert_equal post, tagging.taggable
157
+ end
158
+
159
+ def test_create_polymorphic_has_many_with_scope
160
+ old_count = posts(:welcome).taggings.count
161
+ tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
162
+ assert_equal "Post", tagging.taggable_type
163
+ assert_equal old_count+1, posts(:welcome).taggings.count
164
+ end
165
+
166
+ def test_create_bang_polymorphic_with_has_many_scope
167
+ old_count = posts(:welcome).taggings.count
168
+ tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
169
+ assert_equal "Post", tagging.taggable_type
170
+ assert_equal old_count+1, posts(:welcome).taggings.count
171
+ end
172
+
173
+ def test_create_polymorphic_has_one_with_scope
174
+ old_count = Tagging.count
175
+ tagging = posts(:welcome).create_tagging(:tag => tags(:misc))
176
+ assert_equal "Post", tagging.taggable_type
177
+ assert_equal old_count+1, Tagging.count
178
+ end
179
+
180
+ def test_delete_polymorphic_has_many_with_delete_all
181
+ assert_equal 1, posts(:welcome).taggings.count
182
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDeleteAll'
183
+ post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
184
+
185
+ old_count = Tagging.count
186
+ post.destroy
187
+ assert_equal old_count-1, Tagging.count
188
+ assert_equal 0, posts(:welcome).taggings.count
189
+ end
190
+
191
+ def test_delete_polymorphic_has_many_with_destroy
192
+ assert_equal 1, posts(:welcome).taggings.count
193
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDestroy'
194
+ post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
195
+
196
+ old_count = Tagging.count
197
+ post.destroy
198
+ assert_equal old_count-1, Tagging.count
199
+ assert_equal 0, posts(:welcome).taggings.count
200
+ end
201
+
202
+ def test_delete_polymorphic_has_many_with_nullify
203
+ assert_equal 1, posts(:welcome).taggings.count
204
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyNullify'
205
+ post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
206
+
207
+ old_count = Tagging.count
208
+ post.destroy
209
+ assert_equal old_count, Tagging.count
210
+ assert_equal 0, posts(:welcome).taggings.count
211
+ end
212
+
213
+ def test_delete_polymorphic_has_one_with_destroy
214
+ assert posts(:welcome).tagging
215
+ posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneDestroy'
216
+ post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
217
+
218
+ old_count = Tagging.count
219
+ post.destroy
220
+ assert_equal old_count-1, Tagging.count
221
+ assert_nil posts(:welcome).tagging(true)
222
+ end
223
+
224
+ def test_delete_polymorphic_has_one_with_nullify
225
+ assert posts(:welcome).tagging
226
+ posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneNullify'
227
+ post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
228
+
229
+ old_count = Tagging.count
230
+ post.destroy
231
+ assert_equal old_count, Tagging.count
232
+ assert_nil posts(:welcome).tagging(true)
233
+ end
234
+
235
+ def test_has_many_with_piggyback
236
+ assert_equal "2", categories(:sti_test).authors_with_select.first.post_id.to_s
237
+ end
238
+
239
+ def test_include_has_many_through
240
+ posts = Post.find(:all, :order => 'posts.id')
241
+ posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
242
+ assert_equal posts.length, posts_with_authors.length
243
+ posts.length.times do |i|
244
+ assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
245
+ end
246
+ end
247
+
248
+ def test_include_polymorphic_has_one
249
+ post = Post.find_by_id(posts(:welcome).id, :include => :tagging)
250
+ tagging = taggings(:welcome_general)
251
+ assert_no_queries do
252
+ assert_equal tagging, post.tagging
253
+ end
254
+ end
255
+
256
+ def test_include_polymorphic_has_one_defined_in_abstract_parent
257
+ item = Item.find_by_id(items(:dvd).id, :include => :tagging)
258
+ tagging = taggings(:godfather)
259
+ assert_no_queries do
260
+ assert_equal tagging, item.tagging
261
+ end
262
+ end
263
+
264
+ def test_include_polymorphic_has_many_through
265
+ posts = Post.find(:all, :order => 'posts.id')
266
+ posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
267
+ assert_equal posts.length, posts_with_tags.length
268
+ posts.length.times do |i|
269
+ assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
270
+ end
271
+ end
272
+
273
+ def test_include_polymorphic_has_many
274
+ posts = Post.find(:all, :order => 'posts.id')
275
+ posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
276
+ assert_equal posts.length, posts_with_taggings.length
277
+ posts.length.times do |i|
278
+ assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
279
+ end
280
+ end
281
+
282
+ def test_has_many_find_all
283
+ assert_equal [categories(:general)], authors(:david).categories.find(:all)
284
+ end
285
+
286
+ def test_has_many_find_first
287
+ assert_equal categories(:general), authors(:david).categories.find(:first)
288
+ end
289
+
290
+ def test_has_many_with_hash_conditions
291
+ assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
292
+ end
293
+
294
+ def test_has_many_find_conditions
295
+ assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
296
+ assert_nil authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
297
+ end
298
+
299
+ def test_has_many_class_methods_called_by_method_missing
300
+ assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
301
+ assert_nil authors(:david).categories.find_by_name('Technology')
302
+ end
303
+
304
+ def test_has_many_array_methods_called_by_method_missing
305
+ assert authors(:david).categories.any? { |category| category.name == 'General' }
306
+ assert_nothing_raised { authors(:david).categories.sort }
307
+ end
308
+
309
+ def test_has_many_going_through_join_model_with_custom_foreign_key
310
+ assert_equal [authors(:bob)], posts(:thinking).authors
311
+ assert_equal [authors(:mary)], posts(:authorless).authors
312
+ end
313
+
314
+ def test_has_many_going_through_join_model_with_custom_primary_key
315
+ assert_equal [authors(:david)], posts(:thinking).authors_using_author_id
316
+ end
317
+
318
+ def test_has_many_going_through_polymorphic_join_model_with_custom_primary_key
319
+ assert_equal [tags(:general)], posts(:eager_other).tags_using_author_id
320
+ end
321
+
322
+ def test_has_many_through_with_custom_primary_key_on_belongs_to_source
323
+ assert_equal [authors(:david), authors(:david)], posts(:thinking).author_using_custom_pk
324
+ end
325
+
326
+ def test_has_many_through_with_custom_primary_key_on_has_many_source
327
+ assert_equal [authors(:david), authors(:bob)], posts(:thinking).authors_using_custom_pk.order('authors.id')
328
+ end
329
+
330
+ def test_both_scoped_and_explicit_joins_should_be_respected
331
+ assert_nothing_raised do
332
+ Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
333
+ Post.find :all, :select => "comments.id, authors.id", :joins => "left outer join authors on authors.id = posts.author_id"
334
+ end
335
+ end
336
+ end
337
+
338
+ def test_belongs_to_polymorphic_with_counter_cache
339
+ assert_equal 1, posts(:welcome)[:taggings_count]
340
+ tagging = posts(:welcome).taggings.create(:tag => tags(:general))
341
+ assert_equal 2, posts(:welcome, :reload)[:taggings_count]
342
+ tagging.destroy
343
+ assert_equal 1, posts(:welcome, :reload)[:taggings_count]
344
+ end
345
+
346
+ def test_unavailable_through_reflection
347
+ assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
348
+ end
349
+
350
+ def test_has_many_through_join_model_with_conditions
351
+ assert_equal [], posts(:welcome).invalid_taggings
352
+ assert_equal [], posts(:welcome).invalid_tags
353
+ end
354
+
355
+ def test_has_many_polymorphic
356
+ assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicSourceError do
357
+ tags(:general).taggables
358
+ end
359
+
360
+ assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicThroughError do
361
+ taggings(:welcome_general).things
362
+ end
363
+
364
+ assert_raise ActiveRecord::EagerLoadPolymorphicError do
365
+ tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
366
+ end
367
+ end
368
+
369
+ def test_has_many_polymorphic_with_source_type
370
+ # added sort by ID as otherwise Oracle select sometimes returned rows in different order
371
+ assert_equal posts(:welcome, :thinking).sort_by(&:id), tags(:general).tagged_posts.sort_by(&:id)
372
+ end
373
+
374
+ def test_eager_has_many_polymorphic_with_source_type
375
+ tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
376
+ desired = posts(:welcome, :thinking)
377
+ assert_no_queries do
378
+ # added sort by ID as otherwise test using JRuby was failing as array elements were in different order
379
+ assert_equal desired.sort_by(&:id), tag_with_include.tagged_posts.sort_by(&:id)
380
+ end
381
+ assert_equal 5, tag_with_include.taggings.length
382
+ end
383
+
384
+ def test_has_many_through_has_many_find_all
385
+ assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
386
+ end
387
+
388
+ def test_has_many_through_has_many_find_all_with_custom_class
389
+ assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
390
+ end
391
+
392
+ def test_has_many_through_has_many_find_first
393
+ assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
394
+ end
395
+
396
+ def test_has_many_through_has_many_find_conditions
397
+ options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
398
+ assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
399
+ end
400
+
401
+ def test_has_many_through_has_many_find_by_id
402
+ assert_equal comments(:more_greetings), authors(:david).comments.find(2)
403
+ end
404
+
405
+ def test_has_many_through_polymorphic_has_one
406
+ assert_equal Tagging.find(1,2).sort_by { |t| t.id }, authors(:david).tagging.order(:id)
407
+ end
408
+
409
+ def test_has_many_through_polymorphic_has_many
410
+ assert_equal taggings(:welcome_general, :thinking_general), authors(:david).taggings.uniq.sort_by { |t| t.id }
411
+ end
412
+
413
+ def test_include_has_many_through_polymorphic_has_many
414
+ author = Author.find_by_id(authors(:david).id, :include => :taggings)
415
+ expected_taggings = taggings(:welcome_general, :thinking_general)
416
+ assert_no_queries do
417
+ assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
418
+ end
419
+ end
420
+
421
+ unless current_adapter?(:IBM_DBAdapter)
422
+ # DB2 throws SQL0214N
423
+ def test_eager_load_has_many_through_has_many
424
+ author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
425
+ SpecialComment.new; VerySpecialComment.new
426
+ assert_no_queries do
427
+ assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id)
428
+ end
429
+ end
430
+ end
431
+
432
+ def test_eager_load_has_many_through_has_many_with_conditions
433
+ post = Post.find(:first, :include => :invalid_tags)
434
+ assert_no_queries do
435
+ post.invalid_tags
436
+ end
437
+ end
438
+
439
+ def test_eager_belongs_to_and_has_one_not_singularized
440
+ assert_nothing_raised do
441
+ Author.find(:first, :include => :author_address)
442
+ AuthorAddress.find(:first, :include => :author)
443
+ end
444
+ end
445
+
446
+ def test_self_referential_has_many_through
447
+ assert_equal [authors(:mary)], authors(:david).favorite_authors
448
+ assert_equal [], authors(:mary).favorite_authors
449
+ end
450
+
451
+ def test_add_to_self_referential_has_many_through
452
+ new_author = Author.create(:name => "Bob")
453
+ authors(:david).author_favorites.create :favorite_author => new_author
454
+ assert_equal new_author, authors(:david).reload.favorite_authors.first
455
+ end
456
+
457
+ def test_has_many_through_uses_conditions_specified_on_the_has_many_association
458
+ author = Author.order(:id).first
459
+ assert_present author.comments
460
+ assert_blank author.nonexistant_comments
461
+ end
462
+
463
+ def test_has_many_through_uses_correct_attributes
464
+ assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
465
+ end
466
+
467
+ def test_associating_unsaved_records_with_has_many_through
468
+ saved_post = posts(:thinking)
469
+ new_tag = Tag.new(:name => "new")
470
+
471
+ saved_post.tags << new_tag
472
+ assert new_tag.persisted? #consistent with habtm!
473
+ assert saved_post.persisted?
474
+ assert saved_post.tags.include?(new_tag)
475
+
476
+ assert new_tag.persisted?
477
+ assert new_tag.in?(saved_post.reload.tags(true))
478
+
479
+
480
+ new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.")
481
+ saved_tag = tags(:general)
482
+
483
+ new_post.tags << saved_tag
484
+ assert !new_post.persisted?
485
+ assert saved_tag.persisted?
486
+ assert new_post.tags.include?(saved_tag)
487
+
488
+ new_post.save!
489
+ assert new_post.persisted?
490
+ assert saved_tag.in?(new_post.reload.tags(true))
491
+
492
+ assert !posts(:thinking).tags.build.persisted?
493
+ assert !posts(:thinking).tags.new.persisted?
494
+ end
495
+
496
+ def test_create_associate_when_adding_to_has_many_through
497
+ count = posts(:thinking).tags.count
498
+ push = Tag.create!(:name => 'pushme')
499
+ post_thinking = posts(:thinking)
500
+ assert_nothing_raised { post_thinking.tags << push }
501
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
502
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
503
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
504
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
505
+ assert_equal(count + 1, post_thinking.tags.size)
506
+ assert_equal(count + 1, post_thinking.tags(true).size)
507
+
508
+ assert_kind_of Tag, post_thinking.tags.create!(:name => 'foo')
509
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
510
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
511
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
512
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
513
+ assert_equal(count + 2, post_thinking.tags.size)
514
+ assert_equal(count + 2, post_thinking.tags(true).size)
515
+
516
+ assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
517
+ assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
518
+ message = "Expected a Tag in tags collection, got #{wrong.class}.")
519
+ assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
520
+ message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
521
+ assert_equal(count + 4, post_thinking.tags.size)
522
+ assert_equal(count + 4, post_thinking.tags(true).size)
523
+
524
+ # Raises if the wrong reflection name is used to set the Edge belongs_to
525
+ assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
526
+ end
527
+
528
+ def test_add_to_join_table_with_no_id
529
+ assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
530
+ end
531
+
532
+ def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
533
+ author = authors(:david)
534
+ assert_equal 10, author.comments.size
535
+ assert !author.comments.loaded?
536
+ end
537
+
538
+ def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
539
+ c = categories(:general)
540
+ c.categorizations_count = 100
541
+ assert_equal 100, c.categorizations.size
542
+ assert !c.categorizations.loaded?
543
+ end
544
+
545
+ def test_adding_junk_to_has_many_through_should_raise_type_mismatch
546
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
547
+ end
548
+
549
+ def test_adding_to_has_many_through_should_return_self
550
+ tags = posts(:thinking).tags
551
+ assert_equal tags, posts(:thinking).tags.push(tags(:general))
552
+ end
553
+
554
+ def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_id
555
+ count = books(:awdr).references.count
556
+ references_before = books(:awdr).references
557
+ book = Book.create!(:name => 'Getting Real')
558
+ book_awdr = books(:awdr)
559
+ book_awdr.references << book
560
+ assert_equal(count + 1, book_awdr.references(true).size)
561
+
562
+ assert_nothing_raised { book_awdr.references.delete(book) }
563
+ assert_equal(count, book_awdr.references.size)
564
+ assert_equal(count, book_awdr.references(true).size)
565
+ assert_equal(references_before.sort, book_awdr.references.sort)
566
+ end
567
+
568
+ def test_delete_associate_when_deleting_from_has_many_through
569
+ count = posts(:thinking).tags.count
570
+ tags_before = posts(:thinking).tags
571
+ tag = Tag.create!(:name => 'doomed')
572
+ post_thinking = posts(:thinking)
573
+ post_thinking.tags << tag
574
+ assert_equal(count + 1, post_thinking.taggings(true).size)
575
+ assert_equal(count + 1, post_thinking.tags(true).size)
576
+
577
+ assert_nothing_raised { post_thinking.tags.delete(tag) }
578
+ assert_equal(count, post_thinking.tags.size)
579
+ assert_equal(count, post_thinking.tags(true).size)
580
+ assert_equal(count, post_thinking.taggings(true).size)
581
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
582
+ end
583
+
584
+ def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
585
+ count = posts(:thinking).tags.count
586
+ tags_before = posts(:thinking).tags
587
+ doomed = Tag.create!(:name => 'doomed')
588
+ doomed2 = Tag.create!(:name => 'doomed2')
589
+ quaked = Tag.create!(:name => 'quaked')
590
+ post_thinking = posts(:thinking)
591
+ post_thinking.tags << doomed << doomed2
592
+ assert_equal(count + 2, post_thinking.tags(true).size)
593
+
594
+ assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
595
+ assert_equal(count, post_thinking.tags.size)
596
+ assert_equal(count, post_thinking.tags(true).size)
597
+ assert_equal(tags_before.sort, post_thinking.tags.sort)
598
+ end
599
+
600
+ def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
601
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
602
+ end
603
+
604
+ def test_has_many_through_sum_uses_calculations
605
+ assert_nothing_raised { authors(:david).comments.sum(:post_id) }
606
+ end
607
+
608
+ def test_calculations_on_has_many_through_should_disambiguate_fields
609
+ assert_nothing_raised { authors(:david).categories.maximum(:id) }
610
+ end
611
+
612
+ def test_calculations_on_has_many_through_should_not_disambiguate_fields_unless_necessary
613
+ assert_nothing_raised { authors(:david).categories.maximum("categories.id") }
614
+ end
615
+
616
+ def test_has_many_through_has_many_with_sti
617
+ assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
618
+ end
619
+
620
+ def test_uniq_has_many_through_should_retain_order
621
+ comment_ids = authors(:david).comments.map(&:id)
622
+ assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
623
+ assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
624
+ end
625
+
626
+ def test_polymorphic_has_many
627
+ expected = taggings(:welcome_general)
628
+ p = Post.find(posts(:welcome).id, :include => :taggings)
629
+ assert_no_queries {assert p.taggings.include?(expected)}
630
+ assert posts(:welcome).taggings.include?(taggings(:welcome_general))
631
+ end
632
+
633
+ def test_polymorphic_has_one
634
+ expected = posts(:welcome)
635
+
636
+ tagging = Tagging.find(taggings(:welcome_general).id, :include => :taggable)
637
+ assert_no_queries { assert_equal expected, tagging.taggable}
638
+ end
639
+
640
+ def test_polymorphic_belongs_to
641
+ p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable})
642
+ assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable}
643
+ end
644
+
645
+ def test_preload_polymorphic_has_many_through
646
+ posts = Post.find(:all, :order => 'posts.id')
647
+ posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
648
+ assert_equal posts.length, posts_with_tags.length
649
+ posts.length.times do |i|
650
+ assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
651
+ end
652
+ end
653
+
654
+ def test_preload_polymorph_many_types
655
+ taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel'], :order => 'id'
656
+ assert_no_queries do
657
+ taggings.first.taggable.id
658
+ taggings[1].taggable.id
659
+ end
660
+
661
+ taggables = taggings.map(&:taggable)
662
+ assert taggables.include?(items(:dvd))
663
+ assert taggables.include?(posts(:welcome))
664
+ end
665
+
666
+ def test_preload_nil_polymorphic_belongs_to
667
+ assert_nothing_raised do
668
+ Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
669
+ end
670
+ end
671
+
672
+ def test_preload_polymorphic_has_many
673
+ posts = Post.find(:all, :order => 'posts.id')
674
+ posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
675
+ assert_equal posts.length, posts_with_taggings.length
676
+ posts.length.times do |i|
677
+ assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
678
+ end
679
+ end
680
+
681
+ def test_belongs_to_shared_parent
682
+ comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1')
683
+ assert_no_queries do
684
+ assert_equal comments.first.post, comments[1].post
685
+ end
686
+ end
687
+
688
+ def test_has_many_through_include_uses_array_include_after_loaded
689
+ david = authors(:david)
690
+ david.categories.class # force load target
691
+
692
+ category = david.categories.first
693
+
694
+ assert_no_queries do
695
+ assert david.categories.loaded?
696
+ assert david.categories.include?(category)
697
+ end
698
+ end
699
+
700
+ def test_has_many_through_include_checks_if_record_exists_if_target_not_loaded
701
+ david = authors(:david)
702
+ category = david.categories.first
703
+
704
+ david.reload
705
+ assert ! david.categories.loaded?
706
+ assert_queries(1) do
707
+ assert david.categories.include?(category)
708
+ end
709
+ assert ! david.categories.loaded?
710
+ end
711
+
712
+ def test_has_many_through_include_returns_false_for_non_matching_record_to_verify_scoping
713
+ david = authors(:david)
714
+ category = Category.create!(:name => 'Not Associated')
715
+
716
+ assert ! david.categories.loaded?
717
+ assert ! david.categories.include?(category)
718
+ end
719
+
720
+ def test_has_many_through_goes_through_all_sti_classes
721
+ sub_sti_post = SubStiPost.create!(:title => 'test', :body => 'test', :author_id => 1)
722
+ new_comment = sub_sti_post.comments.create(:body => 'test')
723
+
724
+ assert_equal [9, 10, new_comment.id], authors(:david).sti_post_comments.map(&:id).sort
725
+ end
726
+
727
+ def test_has_many_with_pluralize_table_names_false
728
+ aircraft = Aircraft.create!(:name => "Airbus 380")
729
+ engine = Engine.create!(:car_id => aircraft.id)
730
+ assert_equal aircraft.engines, [engine]
731
+ end
732
+
733
+ private
734
+ # create dynamic Post models to allow different dependency options
735
+ def find_post_with_dependency(post_id, association, association_name, dependency)
736
+ class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
737
+ Post.find(post_id).update_column :type, class_name
738
+ klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
739
+ klass.table_name = 'posts'
740
+ klass.send(association, association_name, :as => :taggable, :dependent => dependency)
741
+ klass.find(post_id)
742
+ end
743
+ end