ibm_db 2.5.6 → 2.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) 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/test/cases/adapter_test.rb +25 -22
  9. data/test/cases/associations/belongs_to_associations_test.rb +245 -43
  10. data/test/cases/associations/cascaded_eager_loading_test.rb +28 -26
  11. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +60 -156
  12. data/test/cases/associations/join_model_test.rb +96 -146
  13. data/test/cases/attribute_methods_test.rb +98 -33
  14. data/test/cases/base_test.rb +525 -103
  15. data/test/cases/calculations_test.rb +92 -8
  16. data/test/cases/migration_test.rb +533 -207
  17. data/test/cases/persistence_test.rb +636 -0
  18. data/test/cases/query_cache_test.rb +242 -0
  19. data/test/cases/relations_test.rb +1019 -0
  20. data/test/cases/schema_dumper_test.rb +37 -17
  21. data/test/cases/transaction_callbacks_test.rb +300 -0
  22. data/test/cases/validations/uniqueness_validation_test.rb +38 -22
  23. data/test/cases/xml_serialization_test.rb +276 -0
  24. data/test/config.yml +154 -0
  25. data/test/connections/native_ibm_db/connection.rb +2 -0
  26. data/test/models/warehouse_thing.rb +4 -4
  27. data/test/schema/i5/ibm_db_specific_schema.rb +3 -1
  28. data/test/schema/ids/ibm_db_specific_schema.rb +3 -1
  29. data/test/schema/luw/ibm_db_specific_schema.rb +2 -0
  30. data/test/schema/schema.rb +174 -89
  31. data/test/schema/zOS/ibm_db_specific_schema.rb +3 -1
  32. metadata +14 -8
  33. data/test/cases/associations/eager_test.rb +0 -862
  34. data/test/cases/associations/has_many_through_associations_test.rb +0 -461
  35. data/test/cases/finder_test.rb +0 -1088
  36. 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)