ibm_db 2.5.14-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +210 -0
  3. data/LICENSE +18 -0
  4. data/MANIFEST +14 -0
  5. data/ParameterizedQueries README +39 -0
  6. data/README +225 -0
  7. data/ext/Makefile.nt32 +181 -0
  8. data/ext/Makefile.nt32.191 +212 -0
  9. data/ext/extconf.rb +127 -0
  10. data/ext/ibm_db.c +11719 -0
  11. data/ext/ruby_ibm_db.h +240 -0
  12. data/ext/ruby_ibm_db_cli.c +845 -0
  13. data/ext/ruby_ibm_db_cli.h +489 -0
  14. data/init.rb +42 -0
  15. data/lib/IBM_DB.rb +2 -0
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3020 -0
  17. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
  18. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +2 -0
  19. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  20. data/lib/ibm_db.rb +8 -0
  21. data/lib/linux/rb18x/ibm_db.so +0 -0
  22. data/lib/linux/rb19x/ibm_db.so +0 -0
  23. data/lib/linux/rb2x/ibm_db.so +0 -0
  24. data/test/cases/adapter_test.rb +207 -0
  25. data/test/cases/associations/belongs_to_associations_test.rb +711 -0
  26. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -0
  27. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -0
  28. data/test/cases/associations/join_model_test.rb +743 -0
  29. data/test/cases/attribute_methods_test.rb +822 -0
  30. data/test/cases/base_test.rb +2133 -0
  31. data/test/cases/calculations_test.rb +482 -0
  32. data/test/cases/migration_test.rb +2408 -0
  33. data/test/cases/persistence_test.rb +642 -0
  34. data/test/cases/query_cache_test.rb +257 -0
  35. data/test/cases/relations_test.rb +1182 -0
  36. data/test/cases/schema_dumper_test.rb +256 -0
  37. data/test/cases/transaction_callbacks_test.rb +300 -0
  38. data/test/cases/validations/uniqueness_validation_test.rb +299 -0
  39. data/test/cases/xml_serialization_test.rb +408 -0
  40. data/test/config.yml +154 -0
  41. data/test/connections/native_ibm_db/connection.rb +44 -0
  42. data/test/ibm_db_test.rb +25 -0
  43. data/test/models/warehouse_thing.rb +5 -0
  44. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  45. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  46. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  47. data/test/schema/schema.rb +751 -0
  48. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  49. metadata +109 -0
@@ -0,0 +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