ibm_db 2.5.6-x86-mingw32 → 2.5.7-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/CHANGES +6 -0
  2. data/README +1 -1
  3. data/ext/Makefile.nt32 +3 -3
  4. data/ext/Makefile.nt32.191 +212 -0
  5. data/ext/ibm_db.c +30 -5
  6. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +300 -108
  7. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1 -1
  8. data/lib/mswin32/rb18x/ibm_db.so +0 -0
  9. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  10. data/test/cases/adapter_test.rb +25 -22
  11. data/test/cases/associations/belongs_to_associations_test.rb +245 -43
  12. data/test/cases/associations/cascaded_eager_loading_test.rb +28 -26
  13. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +60 -156
  14. data/test/cases/associations/join_model_test.rb +96 -146
  15. data/test/cases/attribute_methods_test.rb +98 -33
  16. data/test/cases/base_test.rb +525 -103
  17. data/test/cases/calculations_test.rb +92 -8
  18. data/test/cases/migration_test.rb +533 -207
  19. data/test/cases/persistence_test.rb +636 -0
  20. data/test/cases/query_cache_test.rb +242 -0
  21. data/test/cases/relations_test.rb +1019 -0
  22. data/test/cases/schema_dumper_test.rb +37 -17
  23. data/test/cases/transaction_callbacks_test.rb +300 -0
  24. data/test/cases/validations/uniqueness_validation_test.rb +38 -22
  25. data/test/cases/xml_serialization_test.rb +276 -0
  26. data/test/config.yml +154 -0
  27. data/test/connections/native_ibm_db/connection.rb +2 -0
  28. data/test/models/warehouse_thing.rb +4 -4
  29. data/test/schema/i5/ibm_db_specific_schema.rb +3 -1
  30. data/test/schema/ids/ibm_db_specific_schema.rb +3 -1
  31. data/test/schema/luw/ibm_db_specific_schema.rb +2 -0
  32. data/test/schema/schema.rb +174 -89
  33. data/test/schema/zOS/ibm_db_specific_schema.rb +3 -1
  34. metadata +10 -7
  35. data/test/cases/associations/eager_test.rb +0 -862
  36. data/test/cases/associations/has_many_through_associations_test.rb +0 -461
  37. data/test/cases/finder_test.rb +0 -1088
  38. data/test/cases/fixtures_test.rb +0 -684
@@ -1,7 +1,9 @@
1
1
  require "cases/helper"
2
+ require 'active_support/core_ext/object/inclusion'
2
3
  require 'models/tag'
3
4
  require 'models/tagging'
4
5
  require 'models/post'
6
+ require 'models/rating'
5
7
  require 'models/item'
6
8
  require 'models/comment'
7
9
  require 'models/author'
@@ -11,9 +13,13 @@ require 'models/vertex'
11
13
  require 'models/edge'
12
14
  require 'models/book'
13
15
  require 'models/citation'
16
+ require 'models/aircraft'
17
+ require 'models/engine'
18
+ require 'models/car'
14
19
 
15
20
  class AssociationsJoinModelTest < ActiveRecord::TestCase
16
- self.use_transactional_fixtures = false
21
+ self.use_transactional_fixtures = false unless supports_savepoints?
22
+
17
23
  fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books,
18
24
  # Reload edges table from fixtures as otherwise repeated test was failing
19
25
  :edges
@@ -43,43 +49,14 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
43
49
  assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
44
50
  assert !authors(:mary).unique_categorized_posts.loaded?
45
51
  end
46
-
47
- unless current_adapter?(:IBM_DBAdapter)
48
- def test_has_many_uniq_through_find
49
- assert_equal 1, authors(:mary).unique_categorized_posts.find(:all).size
50
- end
51
-
52
- def test_has_many_uniq_through_dynamic_find
53
- assert_equal 1, authors(:mary).unique_categorized_posts.find_all_by_title("So I was thinking").size
54
- end
55
- # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
56
- # An expression in the ORDER BY clause in the following position,
57
- # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
58
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
59
- # SELECT DISTINCT projects.id FROM projects
60
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
61
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
62
- # ORDER BY developers.created_at
63
- #
64
- # i5: [IBM][CLI Driver][AS] SQL0214N
65
- # An expression in the ORDER BY clause in the following position,
66
- # or starting with "1" in the "CREATED_AT" clause is not valid.
67
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
68
- # SELECT DISTINCT projects.id FROM projects
69
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
70
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
71
- # ORDER BY developers.created_at
72
- #
73
- # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
74
- # An expression in the ORDER BY clause in the following position,
75
- # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
76
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
77
- # SELECT DISTINCT projects.id FROM projects
78
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
79
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
80
- # ORDER BY developers.created_at
81
- #
82
- 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
83
60
 
84
61
  def test_polymorphic_has_many_going_through_join_model
85
62
  assert_equal tags(:general), tag = posts(:welcome).tags.first
@@ -114,16 +91,9 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
114
91
  end
115
92
  end
116
93
 
117
- def test_polymorphic_has_many_going_through_join_model_with_disabled_include
118
- assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
119
- assert_queries 1 do
120
- tag.tagging
121
- end
122
- end
123
-
124
94
  def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
125
95
  assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
126
- tag.author_id
96
+ assert_nothing_raised(NoMethodError) { tag.author_id }
127
97
  end
128
98
 
129
99
  def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
@@ -169,7 +139,21 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
169
139
  def test_set_polymorphic_has_one
170
140
  tagging = tags(:misc).taggings.create
171
141
  posts(:thinking).tagging = tagging
172
- assert_equal "Post", tagging.taggable_type
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
173
157
  end
174
158
 
175
159
  def test_create_polymorphic_has_many_with_scope
@@ -188,14 +172,14 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
188
172
 
189
173
  def test_create_polymorphic_has_one_with_scope
190
174
  old_count = Tagging.count
191
- tagging = posts(:welcome).tagging.create(:tag => tags(:misc))
175
+ tagging = posts(:welcome).create_tagging(:tag => tags(:misc))
192
176
  assert_equal "Post", tagging.taggable_type
193
177
  assert_equal old_count+1, Tagging.count
194
178
  end
195
179
 
196
180
  def test_delete_polymorphic_has_many_with_delete_all
197
181
  assert_equal 1, posts(:welcome).taggings.count
198
- posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll'
182
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDeleteAll'
199
183
  post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
200
184
 
201
185
  old_count = Tagging.count
@@ -206,7 +190,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
206
190
 
207
191
  def test_delete_polymorphic_has_many_with_destroy
208
192
  assert_equal 1, posts(:welcome).taggings.count
209
- posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy'
193
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyDestroy'
210
194
  post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
211
195
 
212
196
  old_count = Tagging.count
@@ -217,7 +201,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
217
201
 
218
202
  def test_delete_polymorphic_has_many_with_nullify
219
203
  assert_equal 1, posts(:welcome).taggings.count
220
- posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify'
204
+ posts(:welcome).taggings.first.update_column :taggable_type, 'PostWithHasManyNullify'
221
205
  post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
222
206
 
223
207
  old_count = Tagging.count
@@ -228,7 +212,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
228
212
 
229
213
  def test_delete_polymorphic_has_one_with_destroy
230
214
  assert posts(:welcome).tagging
231
- posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy'
215
+ posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneDestroy'
232
216
  post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
233
217
 
234
218
  old_count = Tagging.count
@@ -239,7 +223,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
239
223
 
240
224
  def test_delete_polymorphic_has_one_with_nullify
241
225
  assert posts(:welcome).tagging
242
- posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify'
226
+ posts(:welcome).tagging.update_column :taggable_type, 'PostWithHasOneNullify'
243
227
  post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
244
228
 
245
229
  old_count = Tagging.count
@@ -249,7 +233,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
249
233
  end
250
234
 
251
235
  def test_has_many_with_piggyback
252
- assert_equal "2", categories(:sti_test).authors.first.post_id.to_s
236
+ assert_equal "2", categories(:sti_test).authors_with_select.first.post_id.to_s
253
237
  end
254
238
 
255
239
  def test_include_has_many_through
@@ -323,10 +307,26 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
323
307
  end
324
308
 
325
309
  def test_has_many_going_through_join_model_with_custom_foreign_key
326
- assert_equal [], posts(:thinking).authors
310
+ assert_equal [authors(:bob)], posts(:thinking).authors
327
311
  assert_equal [authors(:mary)], posts(:authorless).authors
328
312
  end
329
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
330
  def test_both_scoped_and_explicit_joins_should_be_respected
331
331
  assert_nothing_raised do
332
332
  Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
@@ -353,11 +353,16 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
353
353
  end
354
354
 
355
355
  def test_has_many_polymorphic
356
- assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicError do
357
- assert_equal posts(:welcome, :thinking), tags(:general).taggables
356
+ assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicSourceError do
357
+ tags(:general).taggables
358
+ end
359
+
360
+ assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicThroughError do
361
+ taggings(:welcome_general).things
358
362
  end
363
+
359
364
  assert_raise ActiveRecord::EagerLoadPolymorphicError do
360
- assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
365
+ tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
361
366
  end
362
367
  end
363
368
 
@@ -413,50 +418,16 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
413
418
  end
414
419
  end
415
420
 
416
- def test_has_many_through_has_many_through
417
- assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags }
418
- end
419
-
420
- def test_has_many_through_habtm
421
- assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories }
422
- end
423
-
424
- unless current_adapter?(:IBM_DBAdapter)
421
+ unless current_adapter?(:IBM_DBAdapter)
422
+ # DB2 throws SQL0214N
425
423
  def test_eager_load_has_many_through_has_many
426
424
  author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
427
425
  SpecialComment.new; VerySpecialComment.new
428
426
  assert_no_queries do
429
- assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id)
427
+ assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id)
430
428
  end
431
429
  end
432
- # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
433
- # An expression in the ORDER BY clause in the following position,
434
- # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
435
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
436
- # SELECT DISTINCT projects.id FROM projects
437
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
438
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
439
- # ORDER BY developers.created_at
440
- #
441
- # i5: [IBM][CLI Driver][AS] SQL0214N
442
- # An expression in the ORDER BY clause in the following position,
443
- # or starting with "1" in the "CREATED_AT" clause is not valid.
444
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
445
- # SELECT DISTINCT projects.id FROM projects
446
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
447
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
448
- # ORDER BY developers.created_at
449
- #
450
- # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
451
- # An expression in the ORDER BY clause in the following position,
452
- # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
453
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
454
- # SELECT DISTINCT projects.id FROM projects
455
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
456
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
457
- # ORDER BY developers.created_at
458
- #
459
- end
430
+ end
460
431
 
461
432
  def test_eager_load_has_many_through_has_many_with_conditions
462
433
  post = Post.find(:first, :include => :invalid_tags)
@@ -503,7 +474,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
503
474
  assert saved_post.tags.include?(new_tag)
504
475
 
505
476
  assert new_tag.persisted?
506
- assert saved_post.reload.tags(true).include?(new_tag)
477
+ assert new_tag.in?(saved_post.reload.tags(true))
507
478
 
508
479
 
509
480
  new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.")
@@ -516,7 +487,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
516
487
 
517
488
  new_post.save!
518
489
  assert new_post.persisted?
519
- assert new_post.reload.tags(true).include?(saved_tag)
490
+ assert saved_tag.in?(new_post.reload.tags(true))
520
491
 
521
492
  assert !posts(:thinking).tags.build.persisted?
522
493
  assert !posts(:thinking).tags.new.persisted?
@@ -554,17 +525,21 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
554
525
  assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
555
526
  end
556
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
+
557
532
  def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
558
533
  author = authors(:david)
559
- assert_equal 9, author.comments.size
534
+ assert_equal 10, author.comments.size
560
535
  assert !author.comments.loaded?
561
536
  end
562
537
 
563
538
  def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
564
- author = authors(:david)
565
- author.stubs(:read_attribute).with('comments_count').returns(100)
566
- assert_equal 100, author.comments.size
567
- assert !author.comments.loaded?
539
+ c = categories(:general)
540
+ c.categorizations_count = 100
541
+ assert_equal 100, c.categorizations.size
542
+ assert !c.categorizations.loaded?
568
543
  end
569
544
 
570
545
  def test_adding_junk_to_has_many_through_should_raise_type_mismatch
@@ -645,37 +620,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
645
620
  def test_uniq_has_many_through_should_retain_order
646
621
  comment_ids = authors(:david).comments.map(&:id)
647
622
  assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
648
-
649
- unless current_adapter?(:IBM_DBAdapter)
650
- assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
651
- # LUW: [IBM][CLI Driver][DB2/LINUX] SQL0214N
652
- # An expression in the ORDER BY clause in the following position,
653
- # or starting with "DEVELOPERS" in the "ORDER BY" clause is not valid.
654
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
655
- # SELECT DISTINCT projects.id FROM projects
656
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
657
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
658
- # ORDER BY developers.created_at
659
- #
660
- # i5: [IBM][CLI Driver][AS] SQL0214N
661
- # An expression in the ORDER BY clause in the following position,
662
- # or starting with "1" in the "CREATED_AT" clause is not valid.
663
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
664
- # SELECT DISTINCT projects.id FROM projects
665
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
666
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
667
- # ORDER BY developers.created_at
668
- #
669
- # zOS 9:[IBM][CLI Driver][DB2] SQL0214N
670
- # An expression in the ORDER BY clause in the following position,
671
- # or starting with "CREATED_AT" in the "ORDER BY" clause is not valid.
672
- # Reason code = "2". SQLSTATE=42822 SQLCODE=-214:
673
- # SELECT DISTINCT projects.id FROM projects
674
- # LEFT OUTER JOIN developers_projects ON developers_projects.project_id = projects.id
675
- # LEFT OUTER JOIN developers ON developers.id = developers_projects.developer_id
676
- # ORDER BY developers.created_at
677
- #
678
- end
623
+ assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
679
624
  end
680
625
 
681
626
  def test_polymorphic_has_many
@@ -720,7 +665,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
720
665
 
721
666
  def test_preload_nil_polymorphic_belongs_to
722
667
  assert_nothing_raised do
723
- taggings = Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
668
+ Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
724
669
  end
725
670
  end
726
671
 
@@ -763,16 +708,15 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
763
708
  end
764
709
  assert ! david.categories.loaded?
765
710
  end
766
-
767
- unless current_adapter?(:IBM_DBAdapter) #works fine stand alone, however when run as part of whole suite it breaks unique constraint
768
- def test_has_many_through_include_returns_false_for_non_matching_record_to_verify_scoping
769
- david = authors(:david)
770
- category = Category.create!(:name => 'Not Associated')
771
-
772
- assert ! david.categories.loaded?
773
- assert ! david.categories.include?(category)
774
- end
775
- 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
+
776
720
  def test_has_many_through_goes_through_all_sti_classes
777
721
  sub_sti_post = SubStiPost.create!(:title => 'test', :body => 'test', :author_id => 1)
778
722
  new_comment = sub_sti_post.comments.create(:body => 'test')
@@ -780,11 +724,17 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
780
724
  assert_equal [9, 10, new_comment.id], authors(:david).sti_post_comments.map(&:id).sort
781
725
  end
782
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
+
783
733
  private
784
734
  # create dynamic Post models to allow different dependency options
785
735
  def find_post_with_dependency(post_id, association, association_name, dependency)
786
736
  class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
787
- Post.find(post_id).update_attribute :type, class_name
737
+ Post.find(post_id).update_column :type, class_name
788
738
  klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
789
739
  klass.set_table_name 'posts'
790
740
  klass.send(association, association_name, :as => :taggable, :dependent => dependency)
@@ -1,4 +1,5 @@
1
1
  require "cases/helper"
2
+ require 'active_support/core_ext/object/inclusion'
2
3
  require 'models/minimalistic'
3
4
  require 'models/developer'
4
5
  require 'models/auto_id'
@@ -8,6 +9,8 @@ require 'models/topic'
8
9
  require 'models/company'
9
10
  require 'models/category'
10
11
  require 'models/reply'
12
+ require 'models/contact'
13
+ require 'models/keyboard'
11
14
 
12
15
  class AttributeMethodsTest < ActiveRecord::TestCase
13
16
  fixtures :topics, :developers, :companies, :computers
@@ -75,6 +78,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
75
78
  def test_respond_to?
76
79
  topic = Topic.find(1)
77
80
  assert_respond_to topic, "title"
81
+ assert_respond_to topic, "_title"
78
82
  assert_respond_to topic, "title?"
79
83
  assert_respond_to topic, "title="
80
84
  assert_respond_to topic, :title
@@ -86,6 +90,25 @@ class AttributeMethodsTest < ActiveRecord::TestCase
86
90
  assert !topic.respond_to?(:nothingness)
87
91
  end
88
92
 
93
+ def test_respond_to_with_custom_primary_key
94
+ keyboard = Keyboard.create
95
+ assert_not_nil keyboard.key_number
96
+ assert_equal keyboard.key_number, keyboard.id
97
+ assert keyboard.respond_to?('key_number')
98
+ assert keyboard.respond_to?('_key_number')
99
+ assert keyboard.respond_to?('id')
100
+ assert keyboard.respond_to?('_id')
101
+ end
102
+
103
+ # Syck calls respond_to? before actually calling initialize
104
+ def test_respond_to_with_allocated_object
105
+ topic = Topic.allocate
106
+ assert !topic.respond_to?("nothingness")
107
+ assert !topic.respond_to?(:nothingness)
108
+ assert_respond_to topic, "title"
109
+ assert_respond_to topic, :title
110
+ end
111
+
89
112
  def test_array_content
90
113
  topic = Topic.new
91
114
  topic.content = %w( one two three )
@@ -96,34 +119,55 @@ class AttributeMethodsTest < ActiveRecord::TestCase
96
119
 
97
120
  def test_read_attributes_before_type_cast
98
121
  category = Category.new({:name=>"Test categoty", :type => nil})
99
- category_attrs = {"name"=>"Test categoty", "type" => nil, "categorizations_count" => nil}
122
+ category_attrs = {"name"=>"Test categoty", "id" => nil, "type" => nil, "categorizations_count" => nil}
100
123
  assert_equal category_attrs , category.attributes_before_type_cast
101
124
  end
102
125
 
103
126
  if current_adapter?(:MysqlAdapter)
104
127
  def test_read_attributes_before_type_cast_on_boolean
105
128
  bool = Boolean.create({ "value" => false })
106
- assert_equal "0", bool.reload.attributes_before_type_cast["value"]
129
+ if RUBY_PLATFORM =~ /java/
130
+ # JRuby will return the value before typecast as string
131
+ assert_equal "0", bool.reload.attributes_before_type_cast["value"]
132
+ else
133
+ assert_equal 0, bool.reload.attributes_before_type_cast["value"]
134
+ end
107
135
  end
108
136
  end
109
137
 
110
- unless current_adapter?(:Mysql2Adapter)
111
- def test_read_attributes_before_type_cast_on_datetime
112
- developer = Developer.find(:first)
113
- # Oracle adapter returns Time before type cast
114
- unless current_adapter?(:OracleAdapter)
115
- assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"]
116
- else
117
- assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"].to_s(:db)
138
+ def test_read_attributes_before_type_cast_on_datetime
139
+ in_time_zone "Pacific Time (US & Canada)" do
140
+ record = @target.new
118
141
 
119
- developer.created_at = "345643456"
120
- assert_equal developer.created_at_before_type_cast, "345643456"
121
- assert_equal developer.created_at, nil
142
+ record.written_on = "345643456"
143
+ assert_equal "345643456", record.written_on_before_type_cast
144
+ assert_equal nil, record.written_on
122
145
 
123
- developer.created_at = "2010-03-21 21:23:32"
124
- assert_equal developer.created_at_before_type_cast, "2010-03-21 21:23:32"
125
- assert_equal developer.created_at, Time.parse("2010-03-21 21:23:32")
126
- end
146
+ record.written_on = "2009-10-11 12:13:14"
147
+ assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast
148
+ assert_equal Time.zone.parse("2009-10-11 12:13:14"), record.written_on
149
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
150
+ end
151
+ end
152
+
153
+ def test_read_attributes_after_type_cast_on_datetime
154
+ tz = "Pacific Time (US & Canada)"
155
+
156
+ in_time_zone tz do
157
+ record = @target.new
158
+
159
+ date_string = "2011-03-24"
160
+ time = Time.zone.parse date_string
161
+
162
+ record.written_on = date_string
163
+ assert_equal date_string, record.written_on_before_type_cast
164
+ assert_equal time, record.written_on
165
+ assert_equal ActiveSupport::TimeZone[tz], record.written_on.time_zone
166
+
167
+ record.save
168
+ record.reload
169
+
170
+ assert_equal time, record.written_on
127
171
  end
128
172
  end
129
173
 
@@ -157,7 +201,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
157
201
 
158
202
  def test_case_sensitive_attributes_hash
159
203
  # DB2 is not case-sensitive
160
- return true if current_adapter?(:DB2Adapter)
204
+ return true if current_adapter?(:DB2Adapter,:IBM_DBAdapter)
161
205
 
162
206
  assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.find(:first).attributes
163
207
  end
@@ -238,6 +282,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
238
282
  # puts ""
239
283
  end
240
284
 
285
+ def test_read_overridden_attribute
286
+ topic = Topic.new(:title => 'a')
287
+ def topic.title() 'b' end
288
+ assert_equal 'a', topic[:title]
289
+ end
290
+
241
291
  def test_query_attribute_string
242
292
  [nil, "", " "].each do |value|
243
293
  assert_equal false, Topic.new(:author_name => value).author_name?
@@ -352,7 +402,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
352
402
 
353
403
  def test_typecast_attribute_from_select_to_false
354
404
  topic = Topic.create(:title => 'Budget')
355
- # Oracle does not support boolean expressions in SELECT
405
+ # Oracle and DB2 does not support boolean expressions in SELECT
356
406
  if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
357
407
  topic = Topic.find(:first, :select => "topics.*, 0 as is_test")
358
408
  else
@@ -363,7 +413,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
363
413
 
364
414
  def test_typecast_attribute_from_select_to_true
365
415
  topic = Topic.create(:title => 'Budget')
366
- # Oracle does not support boolean expressions in SELECT
416
+ # Oracle and DB2 does not support boolean expressions in SELECT
367
417
  if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
368
418
  topic = Topic.find(:first, :select => "topics.*, 1 as is_test")
369
419
  else
@@ -419,12 +469,8 @@ class AttributeMethodsTest < ActiveRecord::TestCase
419
469
  Topic.instance_variable_set "@cached_attributes", nil
420
470
  end
421
471
 
422
- def test_time_related_columns_are_actually_cached
423
- column_types = %w(datetime timestamp time date).map(&:to_sym)
424
- column_names = Topic.columns.select{|c| column_types.include?(c.type) }.map(&:name)
425
-
426
- assert_equal column_names.sort, Topic.cached_attributes.sort
427
- assert_equal time_related_columns_on_topic.sort, Topic.cached_attributes.sort
472
+ def test_cacheable_columns_are_actually_cached
473
+ assert_equal cached_columns.sort, Topic.cached_attributes.sort
428
474
  end
429
475
 
430
476
  def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_else
@@ -435,8 +481,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
435
481
  assert cache.empty?
436
482
 
437
483
  all_columns = Topic.columns.map(&:name)
438
- cached_columns = time_related_columns_on_topic
439
- uncached_columns = all_columns - cached_columns
484
+ uncached_columns = all_columns - cached_columns
440
485
 
441
486
  all_columns.each do |attr_name|
442
487
  attribute_gets_cached = Topic.cache_attribute?(attr_name)
@@ -451,6 +496,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
451
496
  end
452
497
  end
453
498
 
499
+ def test_write_nil_to_time_attributes
500
+ in_time_zone "Pacific Time (US & Canada)" do
501
+ record = @target.new
502
+ record.written_on = nil
503
+ assert_nil record.written_on
504
+ end
505
+ end
506
+
454
507
  def test_time_attributes_are_retrieved_in_current_time_zone
455
508
  in_time_zone "Pacific Time (US & Canada)" do
456
509
  utc_time = Time.utc(2008, 1, 1)
@@ -546,7 +599,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
546
599
  topic = @target.new(:title => "The pros and cons of programming naked.")
547
600
  assert !topic.respond_to?(:title)
548
601
  exception = assert_raise(NoMethodError) { topic.title }
549
- assert_equal "Attempt to call private method", exception.message
602
+ assert_match %r(^Attempt to call private method), exception.message
550
603
  assert_equal "I'm private", topic.send(:title)
551
604
  end
552
605
 
@@ -556,7 +609,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
556
609
  topic = @target.new
557
610
  assert !topic.respond_to?(:title=)
558
611
  exception = assert_raise(NoMethodError) { topic.title = "Pants"}
559
- assert_equal "Attempt to call private method", exception.message
612
+ assert_match %r(^Attempt to call private method), exception.message
560
613
  topic.send(:title=, "Very large pants")
561
614
  end
562
615
 
@@ -566,14 +619,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase
566
619
  topic = @target.new(:title => "Isaac Newton's pants")
567
620
  assert !topic.respond_to?(:title?)
568
621
  exception = assert_raise(NoMethodError) { topic.title? }
569
- assert_equal "Attempt to call private method", exception.message
622
+ assert_match %r(^Attempt to call private method), exception.message
570
623
  assert topic.send(:title?)
571
624
  end
572
625
 
573
626
  def test_bulk_update_respects_access_control
574
627
  privatize("title=(value)")
575
628
 
576
- assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title => "Rants about pants") }
629
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
577
630
  assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
578
631
  end
579
632
 
@@ -592,10 +645,22 @@ class AttributeMethodsTest < ActiveRecord::TestCase
592
645
  Object.send(:undef_method, :title) # remove test method from object
593
646
  end
594
647
 
648
+ def test_list_of_serialized_attributes
649
+ assert_equal %w(content), Topic.serialized_attributes.keys
650
+ assert_equal %w(preferences), Contact.serialized_attributes.keys
651
+ end
595
652
 
596
653
  private
654
+ def cached_columns
655
+ @cached_columns ||= (time_related_columns_on_topic + serialized_columns_on_topic).map(&:name)
656
+ end
657
+
597
658
  def time_related_columns_on_topic
598
- Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name)
659
+ Topic.columns.select { |c| c.type.in?([:time, :date, :datetime, :timestamp]) }
660
+ end
661
+
662
+ def serialized_columns_on_topic
663
+ Topic.columns.select { |c| Topic.serialized_attributes.include?(c.name) }
599
664
  end
600
665
 
601
666
  def in_time_zone(zone)