activerecord 2.2.3 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (120) hide show
  1. data/CHANGELOG +438 -396
  2. data/Rakefile +4 -2
  3. data/lib/active_record.rb +46 -43
  4. data/lib/active_record/association_preload.rb +34 -19
  5. data/lib/active_record/associations.rb +193 -251
  6. data/lib/active_record/associations/association_collection.rb +38 -21
  7. data/lib/active_record/associations/association_proxy.rb +11 -4
  8. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +2 -2
  9. data/lib/active_record/associations/has_many_association.rb +2 -2
  10. data/lib/active_record/associations/has_many_through_association.rb +8 -8
  11. data/lib/active_record/associations/has_one_association.rb +11 -2
  12. data/lib/active_record/attribute_methods.rb +1 -0
  13. data/lib/active_record/autosave_association.rb +349 -0
  14. data/lib/active_record/base.rb +292 -106
  15. data/lib/active_record/batches.rb +73 -0
  16. data/lib/active_record/calculations.rb +34 -16
  17. data/lib/active_record/callbacks.rb +37 -8
  18. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +16 -0
  19. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -0
  20. data/lib/active_record/connection_adapters/abstract/database_statements.rb +103 -15
  21. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -6
  22. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +28 -25
  23. data/lib/active_record/connection_adapters/abstract_adapter.rb +29 -5
  24. data/lib/active_record/connection_adapters/mysql_adapter.rb +50 -21
  25. data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -41
  26. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  27. data/lib/active_record/connection_adapters/sqlite_adapter.rb +41 -21
  28. data/lib/active_record/dirty.rb +1 -1
  29. data/lib/active_record/dynamic_scope_match.rb +25 -0
  30. data/lib/active_record/fixtures.rb +193 -198
  31. data/lib/active_record/locale/en.yml +1 -1
  32. data/lib/active_record/locking/optimistic.rb +33 -0
  33. data/lib/active_record/migration.rb +8 -2
  34. data/lib/active_record/named_scope.rb +13 -6
  35. data/lib/active_record/nested_attributes.rb +329 -0
  36. data/lib/active_record/query_cache.rb +25 -13
  37. data/lib/active_record/reflection.rb +6 -1
  38. data/lib/active_record/schema_dumper.rb +2 -0
  39. data/lib/active_record/serialization.rb +3 -1
  40. data/lib/active_record/serializers/json_serializer.rb +19 -0
  41. data/lib/active_record/serializers/xml_serializer.rb +28 -13
  42. data/lib/active_record/session_store.rb +318 -0
  43. data/lib/active_record/test_case.rb +15 -9
  44. data/lib/active_record/timestamp.rb +2 -2
  45. data/lib/active_record/transactions.rb +58 -8
  46. data/lib/active_record/validations.rb +29 -24
  47. data/lib/active_record/version.rb +2 -2
  48. data/test/cases/ar_schema_test.rb +0 -1
  49. data/test/cases/associations/belongs_to_associations_test.rb +35 -131
  50. data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
  51. data/test/cases/associations/eager_load_nested_include_test.rb +29 -0
  52. data/test/cases/associations/eager_test.rb +137 -7
  53. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +45 -7
  54. data/test/cases/associations/has_many_associations_test.rb +110 -149
  55. data/test/cases/associations/has_many_through_associations_test.rb +39 -7
  56. data/test/cases/associations/has_one_associations_test.rb +39 -92
  57. data/test/cases/associations/has_one_through_associations_test.rb +34 -3
  58. data/test/cases/associations/inner_join_association_test.rb +0 -5
  59. data/test/cases/associations/join_model_test.rb +5 -7
  60. data/test/cases/attribute_methods_test.rb +13 -1
  61. data/test/cases/autosave_association_test.rb +901 -0
  62. data/test/cases/base_test.rb +41 -21
  63. data/test/cases/batches_test.rb +61 -0
  64. data/test/cases/calculations_test.rb +37 -17
  65. data/test/cases/callbacks_test.rb +43 -5
  66. data/test/cases/connection_pool_test.rb +25 -0
  67. data/test/cases/copy_table_test_sqlite.rb +11 -0
  68. data/test/cases/datatype_test_postgresql.rb +1 -0
  69. data/test/cases/defaults_test.rb +37 -26
  70. data/test/cases/dirty_test.rb +26 -2
  71. data/test/cases/finder_test.rb +79 -44
  72. data/test/cases/fixtures_test.rb +15 -19
  73. data/test/cases/helper.rb +26 -19
  74. data/test/cases/inheritance_test.rb +2 -2
  75. data/test/cases/json_serialization_test.rb +1 -1
  76. data/test/cases/locking_test.rb +23 -5
  77. data/test/cases/method_scoping_test.rb +126 -3
  78. data/test/cases/migration_test.rb +253 -237
  79. data/test/cases/named_scope_test.rb +73 -3
  80. data/test/cases/nested_attributes_test.rb +509 -0
  81. data/test/cases/query_cache_test.rb +0 -4
  82. data/test/cases/reflection_test.rb +13 -3
  83. data/test/cases/reload_models_test.rb +3 -1
  84. data/test/cases/repair_helper.rb +50 -0
  85. data/test/cases/schema_dumper_test.rb +0 -1
  86. data/test/cases/transactions_test.rb +177 -12
  87. data/test/cases/validations_i18n_test.rb +288 -294
  88. data/test/cases/validations_test.rb +230 -180
  89. data/test/cases/xml_serialization_test.rb +19 -1
  90. data/test/fixtures/fixture_database.sqlite3 +0 -0
  91. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  92. data/test/fixtures/member_types.yml +6 -0
  93. data/test/fixtures/members.yml +3 -1
  94. data/test/fixtures/people.yml +10 -1
  95. data/test/fixtures/toys.yml +4 -0
  96. data/test/models/author.rb +1 -2
  97. data/test/models/bird.rb +3 -0
  98. data/test/models/category.rb +1 -0
  99. data/test/models/company.rb +3 -0
  100. data/test/models/developer.rb +12 -0
  101. data/test/models/event.rb +3 -0
  102. data/test/models/member.rb +1 -0
  103. data/test/models/member_detail.rb +1 -0
  104. data/test/models/member_type.rb +3 -0
  105. data/test/models/owner.rb +2 -1
  106. data/test/models/parrot.rb +2 -0
  107. data/test/models/person.rb +6 -0
  108. data/test/models/pet.rb +2 -1
  109. data/test/models/pirate.rb +55 -1
  110. data/test/models/post.rb +6 -0
  111. data/test/models/project.rb +1 -0
  112. data/test/models/reply.rb +6 -0
  113. data/test/models/ship.rb +8 -1
  114. data/test/models/ship_part.rb +5 -0
  115. data/test/models/topic.rb +13 -1
  116. data/test/models/toy.rb +4 -0
  117. data/test/schema/schema.rb +35 -2
  118. metadata +70 -9
  119. data/test/fixtures/fixture_database.sqlite +0 -0
  120. data/test/fixtures/fixture_database_2.sqlite +0 -0
@@ -6,6 +6,9 @@ require 'models/person'
6
6
  require 'models/developer'
7
7
  require 'models/warehouse_thing'
8
8
  require 'models/guid'
9
+ require 'models/owner'
10
+ require 'models/pet'
11
+ require 'models/event'
9
12
 
10
13
  # The following methods in Topic are used in test_conditional_validation_*
11
14
  class Topic
@@ -31,10 +34,6 @@ class UniqueReply < Reply
31
34
  validates_uniqueness_of :content, :scope => 'parent_id'
32
35
  end
33
36
 
34
- class PlagiarizedReply < Reply
35
- validates_acceptance_of :author_name
36
- end
37
-
38
37
  class SillyUniqueReply < UniqueReply
39
38
  end
40
39
 
@@ -58,11 +57,9 @@ end
58
57
  class ValidationsTest < ActiveRecord::TestCase
59
58
  fixtures :topics, :developers, 'warehouse-things'
60
59
 
61
- def setup
62
- Topic.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
63
- Topic.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
64
- Topic.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
65
- end
60
+ # Most of the tests mess with the validations of Topic, so lets repair it all the time.
61
+ # Other classes we mess with will be dealt with in the specific tests
62
+ repair_validations(Topic)
66
63
 
67
64
  def test_single_field_validation
68
65
  r = Reply.new
@@ -117,8 +114,8 @@ class ValidationsTest < ActiveRecord::TestCase
117
114
  end
118
115
 
119
116
  def test_invalid_record_exception
120
- assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
121
- assert_raises(ActiveRecord::RecordInvalid) { Reply.new.save! }
117
+ assert_raise(ActiveRecord::RecordInvalid) { Reply.create! }
118
+ assert_raise(ActiveRecord::RecordInvalid) { Reply.new.save! }
122
119
 
123
120
  begin
124
121
  r = Reply.new
@@ -130,21 +127,21 @@ class ValidationsTest < ActiveRecord::TestCase
130
127
  end
131
128
 
132
129
  def test_exception_on_create_bang_many
133
- assert_raises(ActiveRecord::RecordInvalid) do
130
+ assert_raise(ActiveRecord::RecordInvalid) do
134
131
  Reply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
135
132
  end
136
133
  end
137
-
134
+
138
135
  def test_exception_on_create_bang_with_block
139
- assert_raises(ActiveRecord::RecordInvalid) do
136
+ assert_raise(ActiveRecord::RecordInvalid) do
140
137
  Reply.create!({ "title" => "OK" }) do |r|
141
138
  r.content = nil
142
139
  end
143
140
  end
144
141
  end
145
-
142
+
146
143
  def test_exception_on_create_bang_many_with_block
147
- assert_raises(ActiveRecord::RecordInvalid) do
144
+ assert_raise(ActiveRecord::RecordInvalid) do
148
145
  Reply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
149
146
  r.content = nil
150
147
  end
@@ -153,7 +150,7 @@ class ValidationsTest < ActiveRecord::TestCase
153
150
 
154
151
  def test_scoped_create_without_attributes
155
152
  Reply.with_scope(:create => {}) do
156
- assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
153
+ assert_raise(ActiveRecord::RecordInvalid) { Reply.create! }
157
154
  end
158
155
  end
159
156
 
@@ -173,7 +170,7 @@ class ValidationsTest < ActiveRecord::TestCase
173
170
  assert_equal person.first_name, "Mary", "should be ok when no attributes are passed to create!"
174
171
  end
175
172
  end
176
- end
173
+ end
177
174
 
178
175
  def test_single_error_per_attr_iteration
179
176
  r = Reply.new
@@ -229,21 +226,16 @@ class ValidationsTest < ActiveRecord::TestCase
229
226
  end
230
227
 
231
228
  def test_validates_each
232
- perform = true
233
229
  hits = 0
234
230
  Topic.validates_each(:title, :content, [:title, :content]) do |record, attr|
235
- if perform
236
- record.errors.add attr, 'gotcha'
237
- hits += 1
238
- end
231
+ record.errors.add attr, 'gotcha'
232
+ hits += 1
239
233
  end
240
234
  t = Topic.new("title" => "valid", "content" => "whatever")
241
235
  assert !t.save
242
236
  assert_equal 4, hits
243
237
  assert_equal %w(gotcha gotcha), t.errors.on(:title)
244
238
  assert_equal %w(gotcha gotcha), t.errors.on(:content)
245
- ensure
246
- perform = false
247
239
  end
248
240
 
249
241
  def test_no_title_confirmation
@@ -315,8 +307,12 @@ class ValidationsTest < ActiveRecord::TestCase
315
307
  end
316
308
 
317
309
  def test_validates_acceptance_of_as_database_column
318
- reply = PlagiarizedReply.create("author_name" => "Dan Brown")
319
- assert_equal "Dan Brown", reply["author_name"]
310
+ repair_validations(Reply) do
311
+ Reply.validates_acceptance_of(:author_name)
312
+
313
+ reply = Reply.create("author_name" => "Dan Brown")
314
+ assert_equal "Dan Brown", reply["author_name"]
315
+ end
320
316
  end
321
317
 
322
318
  def test_validates_acceptance_of_with_non_existant_table
@@ -372,22 +368,24 @@ class ValidationsTest < ActiveRecord::TestCase
372
368
  end
373
369
 
374
370
  def test_validate_uniqueness_with_scope
375
- Reply.validates_uniqueness_of(:content, :scope => "parent_id")
371
+ repair_validations(Reply) do
372
+ Reply.validates_uniqueness_of(:content, :scope => "parent_id")
376
373
 
377
- t = Topic.create("title" => "I'm unique!")
374
+ t = Topic.create("title" => "I'm unique!")
378
375
 
379
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
380
- assert r1.valid?, "Saving r1"
376
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
377
+ assert r1.valid?, "Saving r1"
381
378
 
382
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
383
- assert !r2.valid?, "Saving r2 first time"
379
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
380
+ assert !r2.valid?, "Saving r2 first time"
384
381
 
385
- r2.content = "something else"
386
- assert r2.save, "Saving r2 second time"
382
+ r2.content = "something else"
383
+ assert r2.save, "Saving r2 second time"
387
384
 
388
- t2 = Topic.create("title" => "I'm unique too!")
389
- r3 = t2.replies.create "title" => "r3", "content" => "hello world"
390
- assert r3.valid?, "Saving r3"
385
+ t2 = Topic.create("title" => "I'm unique too!")
386
+ r3 = t2.replies.create "title" => "r3", "content" => "hello world"
387
+ assert r3.valid?, "Saving r3"
388
+ end
391
389
  end
392
390
 
393
391
  def test_validate_uniqueness_scoped_to_defining_class
@@ -406,27 +404,29 @@ class ValidationsTest < ActiveRecord::TestCase
406
404
  end
407
405
 
408
406
  def test_validate_uniqueness_with_scope_array
409
- Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
407
+ repair_validations(Reply) do
408
+ Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
410
409
 
411
- t = Topic.create("title" => "The earth is actually flat!")
410
+ t = Topic.create("title" => "The earth is actually flat!")
412
411
 
413
- r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
414
- assert r1.valid?, "Saving r1"
412
+ r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
413
+ assert r1.valid?, "Saving r1"
415
414
 
416
- r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
417
- assert !r2.valid?, "Saving r2. Double reply by same author."
415
+ r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
416
+ assert !r2.valid?, "Saving r2. Double reply by same author."
418
417
 
419
- r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
420
- assert r2.save, "Saving r2 the second time."
418
+ r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
419
+ assert r2.save, "Saving r2 the second time."
421
420
 
422
- r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
423
- assert !r3.valid?, "Saving r3"
421
+ r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
422
+ assert !r3.valid?, "Saving r3"
424
423
 
425
- r3.author_name = "jj"
426
- assert r3.save, "Saving r3 the second time."
424
+ r3.author_name = "jj"
425
+ assert r3.save, "Saving r3 the second time."
427
426
 
428
- r3.author_name = "jeremy"
429
- assert !r3.save, "Saving r3 the third time."
427
+ r3.author_name = "jeremy"
428
+ assert !r3.save, "Saving r3 the third time."
429
+ end
430
430
  end
431
431
 
432
432
  def test_validate_case_insensitive_uniqueness
@@ -523,10 +523,20 @@ class ValidationsTest < ActiveRecord::TestCase
523
523
  end
524
524
 
525
525
  def test_validate_uniqueness_with_columns_which_are_sql_keywords
526
- Guid.validates_uniqueness_of :key
527
- g = Guid.new
528
- g.key = "foo"
529
- assert_nothing_raised { !g.valid? }
526
+ repair_validations(Guid) do
527
+ Guid.validates_uniqueness_of :key
528
+ g = Guid.new
529
+ g.key = "foo"
530
+ assert_nothing_raised { !g.valid? }
531
+ end
532
+ end
533
+
534
+ def test_validate_uniqueness_with_limit
535
+ # Event.title is limited to 5 characters
536
+ e1 = Event.create(:title => "abcde")
537
+ assert e1.valid?, "Could not create an event with a unique, 5 character title"
538
+ e2 = Event.create(:title => "abcdefgh")
539
+ assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
530
540
  end
531
541
 
532
542
  def test_validate_straight_inheritance_uniqueness
@@ -648,10 +658,12 @@ class ValidationsTest < ActiveRecord::TestCase
648
658
  end
649
659
 
650
660
  def test_numericality_with_getter_method
651
- Developer.validates_numericality_of( :salary )
652
- developer = Developer.new("name" => "michael", "salary" => nil)
653
- developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
654
- assert developer.valid?
661
+ repair_validations(Developer) do
662
+ Developer.validates_numericality_of( :salary )
663
+ developer = Developer.new("name" => "michael", "salary" => nil)
664
+ developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
665
+ assert developer.valid?
666
+ end
655
667
  end
656
668
 
657
669
  def test_validates_length_of_with_allow_nil
@@ -684,10 +696,12 @@ class ValidationsTest < ActiveRecord::TestCase
684
696
  end
685
697
 
686
698
  def test_numericality_with_allow_nil_and_getter_method
687
- Developer.validates_numericality_of( :salary, :allow_nil => true)
688
- developer = Developer.new("name" => "michael", "salary" => nil)
689
- developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
690
- assert developer.valid?
699
+ repair_validations(Developer) do
700
+ Developer.validates_numericality_of( :salary, :allow_nil => true)
701
+ developer = Developer.new("name" => "michael", "salary" => nil)
702
+ developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end")
703
+ assert developer.valid?
704
+ end
691
705
  end
692
706
 
693
707
  def test_validates_exclusion_of
@@ -892,26 +906,30 @@ class ValidationsTest < ActiveRecord::TestCase
892
906
  end
893
907
 
894
908
  def test_validates_size_of_association
895
- assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
896
- t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
897
- assert !t.save
898
- assert t.errors.on(:replies)
899
- reply = t.replies.build('title' => 'areply', 'content' => 'whateveragain')
900
- assert t.valid?
909
+ repair_validations(Owner) do
910
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
911
+ o = Owner.new('name' => 'nopets')
912
+ assert !o.save
913
+ assert o.errors.on(:pets)
914
+ pet = o.pets.build('name' => 'apet')
915
+ assert o.valid?
916
+ end
901
917
  end
902
918
 
903
919
  def test_validates_size_of_association_using_within
904
- assert_nothing_raised { Topic.validates_size_of :replies, :within => 1..2 }
905
- t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
906
- assert !t.save
907
- assert t.errors.on(:replies)
908
-
909
- reply = t.replies.build('title' => 'areply', 'content' => 'whateveragain')
910
- assert t.valid?
911
-
912
- 2.times { t.replies.build('title' => 'areply', 'content' => 'whateveragain') }
913
- assert !t.save
914
- assert t.errors.on(:replies)
920
+ repair_validations(Owner) do
921
+ assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
922
+ o = Owner.new('name' => 'nopets')
923
+ assert !o.save
924
+ assert o.errors.on(:pets)
925
+
926
+ pet = o.pets.build('name' => 'apet')
927
+ assert o.valid?
928
+
929
+ 2.times { o.pets.build('name' => 'apet') }
930
+ assert !o.save
931
+ assert o.errors.on(:pets)
932
+ end
915
933
  end
916
934
 
917
935
  def test_validates_length_of_nasty_params
@@ -949,6 +967,19 @@ class ValidationsTest < ActiveRecord::TestCase
949
967
  assert_equal "boo 5", t.errors["title"]
950
968
  end
951
969
 
970
+ def test_validates_length_of_custom_errors_for_in
971
+ Topic.validates_length_of(:title, :in => 10..20, :message => "hoo {{count}}")
972
+ t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
973
+ assert !t.valid?
974
+ assert t.errors.on(:title)
975
+ assert_equal "hoo 10", t.errors["title"]
976
+
977
+ t = Topic.create("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
978
+ assert !t.valid?
979
+ assert t.errors.on(:title)
980
+ assert_equal "hoo 20", t.errors["title"]
981
+ end
982
+
952
983
  def test_validates_length_of_custom_errors_for_maximum_with_too_long
953
984
  Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}" )
954
985
  t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
@@ -1102,13 +1133,15 @@ class ValidationsTest < ActiveRecord::TestCase
1102
1133
  end
1103
1134
 
1104
1135
  def test_validates_size_of_association_utf8
1105
- with_kcode('UTF8') do
1106
- assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
1107
- t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ')
1108
- assert !t.save
1109
- assert t.errors.on(:replies)
1110
- t.replies.build('title' => 'あいうえお', 'content' => 'かきくけこ')
1111
- assert t.valid?
1136
+ repair_validations(Owner) do
1137
+ with_kcode('UTF8') do
1138
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
1139
+ o = Owner.new('name' => 'あいうえおかきくけこ')
1140
+ assert !o.save
1141
+ assert o.errors.on(:pets)
1142
+ o.pets.build('name' => 'あいうえおかきくけこ')
1143
+ assert o.valid?
1144
+ end
1112
1145
  end
1113
1146
  end
1114
1147
 
@@ -1127,14 +1160,16 @@ class ValidationsTest < ActiveRecord::TestCase
1127
1160
  end
1128
1161
 
1129
1162
  def test_validates_associated_one
1130
- Reply.validates_associated( :topic )
1131
- Topic.validates_presence_of( :content )
1132
- r = Reply.new("title" => "A reply", "content" => "with content!")
1133
- r.topic = Topic.create("title" => "uhohuhoh")
1134
- assert !r.valid?
1135
- assert r.errors.on(:topic)
1136
- r.topic.content = "non-empty"
1137
- assert r.valid?
1163
+ repair_validations(Reply) do
1164
+ Reply.validates_associated( :topic )
1165
+ Topic.validates_presence_of( :content )
1166
+ r = Reply.new("title" => "A reply", "content" => "with content!")
1167
+ r.topic = Topic.create("title" => "uhohuhoh")
1168
+ assert !r.valid?
1169
+ assert r.errors.on(:topic)
1170
+ r.topic.content = "non-empty"
1171
+ assert r.valid?
1172
+ end
1138
1173
  end
1139
1174
 
1140
1175
  def test_validate_block
@@ -1158,85 +1193,105 @@ class ValidationsTest < ActiveRecord::TestCase
1158
1193
  end
1159
1194
 
1160
1195
  def test_validates_acceptance_of_with_custom_error_using_quotes
1161
- Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes"
1162
- d = Developer.new
1163
- d.salary = "0"
1164
- assert !d.valid?
1165
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
1196
+ repair_validations(Developer) do
1197
+ Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes"
1198
+ d = Developer.new
1199
+ d.salary = "0"
1200
+ assert !d.valid?
1201
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
1202
+ end
1166
1203
  end
1167
1204
 
1168
1205
  def test_validates_confirmation_of_with_custom_error_using_quotes
1169
- Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
1170
- d = Developer.new
1171
- d.name = "John"
1172
- d.name_confirmation = "Johnny"
1173
- assert !d.valid?
1174
- assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
1206
+ repair_validations(Developer) do
1207
+ Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
1208
+ d = Developer.new
1209
+ d.name = "John"
1210
+ d.name_confirmation = "Johnny"
1211
+ assert !d.valid?
1212
+ assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
1213
+ end
1175
1214
  end
1176
1215
 
1177
1216
  def test_validates_format_of_with_custom_error_using_quotes
1178
- Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
1179
- d = Developer.new
1180
- d.name = d.name_confirmation = "John 32"
1181
- assert !d.valid?
1182
- assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
1217
+ repair_validations(Developer) do
1218
+ Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
1219
+ d = Developer.new
1220
+ d.name = d.name_confirmation = "John 32"
1221
+ assert !d.valid?
1222
+ assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
1223
+ end
1183
1224
  end
1184
1225
 
1185
1226
  def test_validates_inclusion_of_with_custom_error_using_quotes
1186
- Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
1187
- d = Developer.new
1188
- d.salary = "90,000"
1189
- assert !d.valid?
1190
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
1227
+ repair_validations(Developer) do
1228
+ Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
1229
+ d = Developer.new
1230
+ d.salary = "90,000"
1231
+ assert !d.valid?
1232
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).last
1233
+ end
1191
1234
  end
1192
1235
 
1193
1236
  def test_validates_length_of_with_custom_too_long_using_quotes
1194
- Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
1195
- d = Developer.new
1196
- d.name = "Jeffrey"
1197
- assert !d.valid?
1198
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
1237
+ repair_validations(Developer) do
1238
+ Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
1239
+ d = Developer.new
1240
+ d.name = "Jeffrey"
1241
+ assert !d.valid?
1242
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
1243
+ end
1199
1244
  end
1200
1245
 
1201
1246
  def test_validates_length_of_with_custom_too_short_using_quotes
1202
- Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
1203
- d = Developer.new
1204
- d.name = "Joe"
1205
- assert !d.valid?
1206
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
1247
+ repair_validations(Developer) do
1248
+ Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
1249
+ d = Developer.new
1250
+ d.name = "Joe"
1251
+ assert !d.valid?
1252
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
1253
+ end
1207
1254
  end
1208
1255
 
1209
1256
  def test_validates_length_of_with_custom_message_using_quotes
1210
- Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
1211
- d = Developer.new
1212
- d.name = "Joe"
1213
- assert !d.valid?
1214
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
1257
+ repair_validations(Developer) do
1258
+ Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
1259
+ d = Developer.new
1260
+ d.name = "Joe"
1261
+ assert !d.valid?
1262
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
1263
+ end
1215
1264
  end
1216
1265
 
1217
1266
  def test_validates_presence_of_with_custom_message_using_quotes
1218
- Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
1219
- d = Developer.new
1220
- d.name = "Joe"
1221
- assert !d.valid?
1222
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
1267
+ repair_validations(Developer) do
1268
+ Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes"
1269
+ d = Developer.new
1270
+ d.name = "Joe"
1271
+ assert !d.valid?
1272
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
1273
+ end
1223
1274
  end
1224
1275
 
1225
1276
  def test_validates_uniqueness_of_with_custom_message_using_quotes
1226
- Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes"
1227
- d = Developer.new
1228
- d.name = "David"
1229
- assert !d.valid?
1230
- assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).last
1277
+ repair_validations(Developer) do
1278
+ Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes"
1279
+ d = Developer.new
1280
+ d.name = "David"
1281
+ assert !d.valid?
1282
+ assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name)
1283
+ end
1231
1284
  end
1232
1285
 
1233
1286
  def test_validates_associated_with_custom_message_using_quotes
1234
- Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
1235
- Topic.validates_presence_of :content
1236
- r = Reply.create("title" => "A reply", "content" => "with content!")
1237
- r.topic = Topic.create("title" => "uhohuhoh")
1238
- assert !r.valid?
1239
- assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic).last
1287
+ repair_validations(Reply) do
1288
+ Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
1289
+ Topic.validates_presence_of :content
1290
+ r = Reply.create("title" => "A reply", "content" => "with content!")
1291
+ r.topic = Topic.create("title" => "uhohuhoh")
1292
+ assert !r.valid?
1293
+ assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic)
1294
+ end
1240
1295
  end
1241
1296
 
1242
1297
  def test_if_validation_using_method_true
@@ -1346,13 +1401,15 @@ class ValidationsTest < ActiveRecord::TestCase
1346
1401
  end
1347
1402
 
1348
1403
  def test_validates_associated_missing
1349
- Reply.validates_presence_of(:topic)
1350
- r = Reply.create("title" => "A reply", "content" => "with content!")
1351
- assert !r.valid?
1352
- assert r.errors.on(:topic)
1353
-
1354
- r.topic = Topic.find :first
1355
- assert r.valid?
1404
+ repair_validations(Reply) do
1405
+ Reply.validates_presence_of(:topic)
1406
+ r = Reply.create("title" => "A reply", "content" => "with content!")
1407
+ assert !r.valid?
1408
+ assert r.errors.on(:topic)
1409
+
1410
+ r.topic = Topic.find :first
1411
+ assert r.valid?
1412
+ end
1356
1413
  end
1357
1414
 
1358
1415
  def test_errors_to_xml
@@ -1364,14 +1421,25 @@ class ValidationsTest < ActiveRecord::TestCase
1364
1421
  assert xml.include?("<error>Content Empty</error>")
1365
1422
  end
1366
1423
 
1367
- def test_validation_order
1424
+ def test_validation_order
1425
+ Topic.validates_presence_of :title
1426
+ Topic.validates_length_of :title, :minimum => 2
1427
+
1428
+ t = Topic.new("title" => "")
1429
+ assert !t.valid?
1430
+ assert_equal "can't be blank", t.errors.on("title").first
1431
+ end
1432
+
1433
+ def test_invalid_should_be_the_opposite_of_valid
1368
1434
  Topic.validates_presence_of :title
1369
- Topic.validates_length_of :title, :minimum => 2
1370
1435
 
1371
- t = Topic.new("title" => "")
1372
- assert !t.valid?
1373
- assert_equal "can't be blank", t.errors.on("title").first
1374
- end
1436
+ t = Topic.new
1437
+ assert t.invalid?
1438
+ assert t.errors.invalid?(:title)
1439
+
1440
+ t.title = 'Things are going to change'
1441
+ assert !t.invalid?
1442
+ end
1375
1443
 
1376
1444
  # previous implementation of validates_presence_of eval'd the
1377
1445
  # string with the wrong binding, this regression test is to
@@ -1394,20 +1462,6 @@ class ValidationsTest < ActiveRecord::TestCase
1394
1462
  t.author_name = "Hubert J. Farnsworth"
1395
1463
  assert t.valid?, "A topic with an important title and author should be valid"
1396
1464
  end
1397
-
1398
- private
1399
- def with_kcode(kcode)
1400
- if RUBY_VERSION < '1.9'
1401
- orig_kcode, $KCODE = $KCODE, kcode
1402
- begin
1403
- yield
1404
- ensure
1405
- $KCODE = orig_kcode
1406
- end
1407
- else
1408
- yield
1409
- end
1410
- end
1411
1465
  end
1412
1466
 
1413
1467
 
@@ -1423,11 +1477,7 @@ class ValidatesNumericalityTest < ActiveRecord::TestCase
1423
1477
  JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
1424
1478
  INFINITY = [1.0/0.0]
1425
1479
 
1426
- def setup
1427
- Topic.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
1428
- Topic.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
1429
- Topic.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
1430
- end
1480
+ repair_validations(Topic)
1431
1481
 
1432
1482
  def test_default_validates_numericality_of
1433
1483
  Topic.validates_numericality_of :approved