5 require 'models/person'
6 require 'models/developer'
7 require 'models/warehouse_thing'
11 require 'models/event'
13 # The following methods in Topic are used in test_conditional_validation_*
15 has_many
:unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
16 has_many
:silly_unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
22 def condition_is_true_but_its_not
27 class ProtectedPerson
< ActiveRecord
::Base
28 set_table_name
'people'
30 attr_protected
:first_name
33 class UniqueReply
< Reply
34 validates_uniqueness_of
:content, :scope => 'parent_id'
37 class SillyUniqueReply
< UniqueReply
40 class Wizard
< ActiveRecord
::Base
41 self.abstract_class
= true
43 validates_uniqueness_of
:name
46 class IneptWizard
< Wizard
47 validates_uniqueness_of
:city
50 class Conjurer
< IneptWizard
53 class Thaumaturgist
< IneptWizard
57 class ValidationsTest
< ActiveRecord
::TestCase
58 fixtures
:topics, :developers, 'warehouse-things'
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
)
64 def test_single_field_validation
66 r
.title
= "There's no content!"
67 assert
!r
.valid
?, "A reply without content shouldn't be saveable"
69 r
.content
= "Messa content!"
70 assert r
.valid
?, "A reply with content should be saveable"
73 def test_single_attr_validation_and_error_msg
75 r
.title
= "There's no content!"
77 assert r
.errors
.invalid
?("content"), "A reply without content should mark that attribute as invalid"
78 assert_equal
"Empty", r
.errors
.on("content"), "A reply without content should contain an error"
79 assert_equal
1, r
.errors
.count
82 def test_double_attr_validation_and_error_msg
86 assert r
.errors
.invalid
?("title"), "A reply without title should mark that attribute as invalid"
87 assert_equal
"Empty", r
.errors
.on("title"), "A reply without title should contain an error"
89 assert r
.errors
.invalid
?("content"), "A reply without content should mark that attribute as invalid"
90 assert_equal
"Empty", r
.errors
.on("content"), "A reply without content should contain an error"
92 assert_equal
2, r
.errors
.count
95 def test_error_on_create
97 r
.title
= "Wrong Create"
99 assert r
.errors
.invalid
?("title"), "A reply with a bad title should mark that attribute as invalid"
100 assert_equal
"is Wrong Create", r
.errors
.on("title"), "A reply with a bad content should contain an error"
103 def test_error_on_update
107 assert r
.save
, "First save should be successful"
109 r
.title
= "Wrong Update"
110 assert
!r
.save
, "Second save should fail"
112 assert r
.errors
.invalid
?("title"), "A reply with a bad title should mark that attribute as invalid"
113 assert_equal
"is Wrong Update", r
.errors
.on("title"), "A reply with a bad content should contain an error"
116 def test_invalid_record_exception
117 assert_raise(ActiveRecord
::RecordInvalid) { Reply
.create
! }
118 assert_raise(ActiveRecord
::RecordInvalid) { Reply
.new
.save
! }
124 rescue ActiveRecord
::RecordInvalid => invalid
125 assert_equal r
, invalid
.record
129 def test_exception_on_create_bang_many
130 assert_raise(ActiveRecord
::RecordInvalid) do
131 Reply
.create
!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
135 def test_exception_on_create_bang_with_block
136 assert_raise(ActiveRecord
::RecordInvalid) do
137 Reply
.create
!({ "title" => "OK" }) do |r
|
143 def test_exception_on_create_bang_many_with_block
144 assert_raise(ActiveRecord
::RecordInvalid) do
145 Reply
.create
!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r
|
151 def test_scoped_create_without_attributes
152 Reply
.with_scope(:create => {}) do
153 assert_raise(ActiveRecord
::RecordInvalid) { Reply
.create
! }
157 def test_create_with_exceptions_using_scope_for_protected_attributes
158 assert_nothing_raised
do
159 ProtectedPerson
.with_scope( :create => { :first_name => "Mary" } ) do
160 person
= ProtectedPerson
.create
! :addon => "Addon"
161 assert_equal person
.first_name
, "Mary", "scope should ignore attr_protected"
166 def test_create_with_exceptions_using_scope_and_empty_attributes
167 assert_nothing_raised
do
168 ProtectedPerson
.with_scope( :create => { :first_name => "Mary" } ) do
169 person
= ProtectedPerson
.create
!
170 assert_equal person
.first_name
, "Mary", "should be ok when no attributes are passed to create!"
175 def test_single_error_per_attr_iteration
180 r
.errors
.each
{ |attr
, msg
| errors
<< [attr
, msg
] }
182 assert errors
.include?(["title", "Empty"])
183 assert errors
.include?(["content", "Empty"])
186 def test_multiple_errors_per_attr_iteration_with_full_error_composition
188 r
.title
= "Wrong Create"
189 r
.content
= "Mismatch"
193 r
.errors
.each_full
{ |error
| errors
<< error
}
195 assert_equal
"Title is Wrong Create", errors
[0]
196 assert_equal
"Title is Content Mismatch", errors
[1]
197 assert_equal
2, r
.errors
.count
200 def test_errors_on_base
202 r
.content
= "Mismatch"
204 r
.errors
.add_to_base
"Reply is not dignifying"
207 r
.errors
.each_full
{ |error
| errors
<< error
}
209 assert_equal
"Reply is not dignifying", r
.errors
.on_base
211 assert errors
.include?("Title Empty")
212 assert errors
.include?("Reply is not dignifying")
213 assert_equal
2, r
.errors
.count
216 def test_create_without_validation
219 assert reply
.save(false)
222 def test_create_without_validation_bang
224 assert_nothing_raised
{ Reply
.new
.save_without_validation
! }
225 assert count
+1, Reply
.count
228 def test_validates_each
230 Topic
.validates_each(:title, :content, [:title, :content]) do |record
, attr
|
231 record
.errors
.add attr
, 'gotcha'
234 t
= Topic
.new("title" => "valid", "content" => "whatever")
237 assert_equal
%w(gotcha gotcha
), t
.errors
.on(:title)
238 assert_equal
%w(gotcha gotcha
), t
.errors
.on(:content)
241 def test_no_title_confirmation
242 Topic
.validates_confirmation_of(:title)
244 t
= Topic
.new(:author_name => "Plutarch")
247 t
.title_confirmation
= "Parallel Lives"
250 t
.title_confirmation
= nil
251 t
.title
= "Parallel Lives"
254 t
.title_confirmation
= "Parallel Lives"
258 def test_title_confirmation
259 Topic
.validates_confirmation_of(:title)
261 t
= Topic
.create("title" => "We should be confirmed","title_confirmation" => "")
264 t
.title_confirmation
= "We should be confirmed"
268 def test_terms_of_service_agreement_no_acceptance
269 Topic
.validates_acceptance_of(:terms_of_service, :on => :create)
271 t
= Topic
.create("title" => "We should not be confirmed")
275 def test_terms_of_service_agreement
276 Topic
.validates_acceptance_of(:terms_of_service, :on => :create)
278 t
= Topic
.create("title" => "We should be confirmed","terms_of_service" => "")
280 assert_equal
"must be accepted", t
.errors
.on(:terms_of_service)
282 t
.terms_of_service
= "1"
288 Topic
.validates_acceptance_of(:eula, :message => "must be abided", :on => :create)
290 t
= Topic
.create("title" => "We should be confirmed","eula" => "")
292 assert_equal
"must be abided", t
.errors
.on(:eula)
298 def test_terms_of_service_agreement_with_accept_value
299 Topic
.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.")
301 t
= Topic
.create("title" => "We should be confirmed", "terms_of_service" => "")
303 assert_equal
"must be accepted", t
.errors
.on(:terms_of_service)
305 t
.terms_of_service
= "I agree."
309 def test_validates_acceptance_of_as_database_column
310 repair_validations(Reply
) do
311 Reply
.validates_acceptance_of(:author_name)
313 reply
= Reply
.create("author_name" => "Dan Brown")
314 assert_equal
"Dan Brown", reply
["author_name"]
318 def test_validates_acceptance_of_with_non_existant_table
319 Object
.const_set
:IncorporealModel, Class
.new(ActiveRecord
::Base)
321 assert_nothing_raised ActiveRecord
::StatementInvalid do
322 IncorporealModel
.validates_acceptance_of(:incorporeal_column)
326 def test_validate_presences
327 Topic
.validates_presence_of(:title, :content)
331 assert_equal
"can't be blank", t
.errors
.on(:title)
332 assert_equal
"can't be blank", t
.errors
.on(:content)
334 t
.title
= "something"
338 assert_equal
"can't be blank", t
.errors
.on(:content)
340 t
.content
= "like stuff"
345 def test_validate_uniqueness
346 Topic
.validates_uniqueness_of(:title)
348 t
= Topic
.new("title" => "I'm unique!")
349 assert t
.save
, "Should save t as unique"
351 t
.content
= "Remaining unique"
352 assert t
.save
, "Should still save t as unique"
354 t2
= Topic
.new("title" => "I'm unique!")
355 assert
!t2
.valid
?, "Shouldn't be valid"
356 assert
!t2
.save
, "Shouldn't save t2 as unique"
357 assert_equal
"has already been taken", t2
.errors
.on(:title)
359 t2
.title
= "Now Im really also unique"
360 assert t2
.save
, "Should now save t2 as unique"
363 def test_validates_uniquness_with_newline_chars
364 Topic
.validates_uniqueness_of(:title, :case_sensitive => false)
366 t
= Topic
.new("title" => "new\nline")
367 assert t
.save
, "Should save t as unique"
370 def test_validate_uniqueness_with_scope
371 repair_validations(Reply
) do
372 Reply
.validates_uniqueness_of(:content, :scope => "parent_id")
374 t
= Topic
.create("title" => "I'm unique!")
376 r1
= t
.replies
.create
"title" => "r1", "content" => "hello world"
377 assert r1
.valid
?, "Saving r1"
379 r2
= t
.replies
.create
"title" => "r2", "content" => "hello world"
380 assert
!r2
.valid
?, "Saving r2 first time"
382 r2
.content
= "something else"
383 assert r2
.save
, "Saving r2 second time"
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"
391 def test_validate_uniqueness_scoped_to_defining_class
392 t
= Topic
.create("title" => "What, me worry?")
394 r1
= t
.unique_replies
.create
"title" => "r1", "content" => "a barrel of fun"
395 assert r1
.valid
?, "Saving r1"
397 r2
= t
.silly_unique_replies
.create
"title" => "r2", "content" => "a barrel of fun"
398 assert
!r2
.valid
?, "Saving r2"
400 # Should succeed as validates_uniqueness_of only applies to
401 # UniqueReply and its subclasses
402 r3
= t
.replies
.create
"title" => "r2", "content" => "a barrel of fun"
403 assert r3
.valid
?, "Saving r3"
406 def test_validate_uniqueness_with_scope_array
407 repair_validations(Reply
) do
408 Reply
.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
410 t
= Topic
.create("title" => "The earth is actually flat!")
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 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 r2
.author_email_address
= "jeremy_alt_email@rubyonrails.com"
419 assert r2
.save
, "Saving r2 the second time."
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 r3
.author_name
= "jj"
425 assert r3
.save
, "Saving r3 the second time."
427 r3
.author_name
= "jeremy"
428 assert
!r3
.save
, "Saving r3 the third time."
432 def test_validate_case_insensitive_uniqueness
433 Topic
.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
435 t
= Topic
.new("title" => "I'm unique!", :parent_id => 2)
436 assert t
.save
, "Should save t as unique"
438 t
.content
= "Remaining unique"
439 assert t
.save
, "Should still save t as unique"
441 t2
= Topic
.new("title" => "I'm UNIQUE!", :parent_id => 1)
442 assert
!t2
.valid
?, "Shouldn't be valid"
443 assert
!t2
.save
, "Shouldn't save t2 as unique"
444 assert t2
.errors
.on(:title)
445 assert t2
.errors
.on(:parent_id)
446 assert_equal
"has already been taken", t2
.errors
.on(:title)
448 t2
.title
= "I'm truly UNIQUE!"
449 assert
!t2
.valid
?, "Shouldn't be valid"
450 assert
!t2
.save
, "Shouldn't save t2 as unique"
451 assert_nil t2
.errors
.on(:title)
452 assert t2
.errors
.on(:parent_id)
455 assert t2
.save
, "Should now save t2 as unique"
459 assert t2
.valid
?, "should validate with nil"
460 assert t2
.save
, "should save with nil"
462 with_kcode('UTF8') do
463 t_utf8
= Topic
.new("title" => "Я тоже уникальный!")
464 assert t_utf8
.save
, "Should save t_utf8 as unique"
466 # If database hasn't UTF-8 character set, this test fails
467 if Topic
.find(t_utf8
, :select => 'LOWER(title) AS title').title
== "я тоже уникальный!"
468 t2_utf8
= Topic
.new("title" => "я тоже УНИКАЛЬНЫЙ!")
469 assert
!t2_utf8
.valid
?, "Shouldn't be valid"
470 assert
!t2_utf8
.save
, "Shouldn't save t2_utf8 as unique"
475 def test_validate_case_sensitive_uniqueness
476 Topic
.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
478 t
= Topic
.new("title" => "I'm unique!")
479 assert t
.save
, "Should save t as unique"
481 t
.content
= "Remaining unique"
482 assert t
.save
, "Should still save t as unique"
484 t2
= Topic
.new("title" => "I'M UNIQUE!")
485 assert t2
.valid
?, "Should be valid"
486 assert t2
.save
, "Should save t2 as unique"
487 assert
!t2
.errors
.on(:title)
488 assert
!t2
.errors
.on(:parent_id)
489 assert_not_equal
"has already been taken", t2
.errors
.on(:title)
491 t3
= Topic
.new("title" => "I'M uNiQUe!")
492 assert t3
.valid
?, "Should be valid"
493 assert t3
.save
, "Should save t2 as unique"
494 assert
!t3
.errors
.on(:title)
495 assert
!t3
.errors
.on(:parent_id)
496 assert_not_equal
"has already been taken", t3
.errors
.on(:title)
499 def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
500 Topic
.validates_uniqueness_of(:title, :case_sensitve => true)
501 t
= Topic
.create
!('title' => 101)
503 t2
= Topic
.new('title' => 101)
505 assert t2
.errors
.on(:title)
508 def test_validate_uniqueness_with_non_standard_table_names
509 i1
= WarehouseThing
.create(:value => 1000)
510 assert
!i1
.valid
?, "i1 should not be valid"
511 assert i1
.errors
.on(:value), "Should not be empty"
514 def test_validates_uniqueness_inside_with_scope
515 Topic
.validates_uniqueness_of(:title)
517 Topic
.with_scope(:find => { :conditions => { :author_name => "David" } }) do
518 t1
= Topic
.new("title" => "I'm unique!", "author_name" => "Mary")
520 t2
= Topic
.new("title" => "I'm unique!", "author_name" => "David")
525 def test_validate_uniqueness_with_columns_which_are_sql_keywords
526 repair_validations(Guid
) do
527 Guid
.validates_uniqueness_of
:key
530 assert_nothing_raised
{ !g
.valid
? }
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"
542 def test_validate_straight_inheritance_uniqueness
543 w1
= IneptWizard
.create(:name => "Rincewind", :city => "Ankh-Morpork")
544 assert w1
.valid
?, "Saving w1"
546 # Should use validation from base class (which is abstract)
547 w2
= IneptWizard
.new(:name => "Rincewind", :city => "Quirm")
548 assert
!w2
.valid
?, "w2 shouldn't be valid"
549 assert w2
.errors
.on(:name), "Should have errors for name"
550 assert_equal
"has already been taken", w2
.errors
.on(:name), "Should have uniqueness message for name"
552 w3
= Conjurer
.new(:name => "Rincewind", :city => "Quirm")
553 assert
!w3
.valid
?, "w3 shouldn't be valid"
554 assert w3
.errors
.on(:name), "Should have errors for name"
555 assert_equal
"has already been taken", w3
.errors
.on(:name), "Should have uniqueness message for name"
557 w4
= Conjurer
.create(:name => "The Amazing Bonko", :city => "Quirm")
558 assert w4
.valid
?, "Saving w4"
560 w5
= Thaumaturgist
.new(:name => "The Amazing Bonko", :city => "Lancre")
561 assert
!w5
.valid
?, "w5 shouldn't be valid"
562 assert w5
.errors
.on(:name), "Should have errors for name"
563 assert_equal
"has already been taken", w5
.errors
.on(:name), "Should have uniqueness message for name"
565 w6
= Thaumaturgist
.new(:name => "Mustrum Ridcully", :city => "Quirm")
566 assert
!w6
.valid
?, "w6 shouldn't be valid"
567 assert w6
.errors
.on(:city), "Should have errors for city"
568 assert_equal
"has already been taken", w6
.errors
.on(:city), "Should have uniqueness message for city"
571 def test_validate_format
572 Topic
.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
574 t
= Topic
.create("title" => "i'm incorrect", "content" => "Validation macros rule!")
575 assert
!t
.valid
?, "Shouldn't be valid"
576 assert
!t
.save
, "Shouldn't save because it's invalid"
577 assert_equal
"is bad data", t
.errors
.on(:title)
578 assert_nil t
.errors
.on(:content)
580 t
.title
= "Validation macros rule!"
583 assert_nil t
.errors
.on(:title)
585 assert_raise(ArgumentError
) { Topic
.validates_format_of(:title, :content) }
588 def test_validate_format_with_allow_blank
589 Topic
.validates_format_of(:title, :with => /^Validation\smacros \w+!$/, :allow_blank=>true)
590 assert
!Topic
.create("title" => "Shouldn't be valid").valid
?
591 assert Topic
.create("title" => "").valid
?
592 assert Topic
.create("title" => nil).valid
?
593 assert Topic
.create("title" => "Validation macros rule!").valid
?
596 # testing ticket #3142
597 def test_validate_format_numeric
598 Topic
.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data")
600 t
= Topic
.create("title" => "72x", "content" => "6789")
601 assert
!t
.valid
?, "Shouldn't be valid"
602 assert
!t
.save
, "Shouldn't save because it's invalid"
603 assert_equal
"is bad data", t
.errors
.on(:title)
604 assert_nil t
.errors
.on(:content)
607 assert
!t
.valid
?, "Shouldn't be valid"
610 assert
!t
.valid
?, "Shouldn't be valid"
613 assert
!t
.valid
?, "Shouldn't be valid"
616 assert
!t
.valid
?, "Shouldn't be valid"
621 assert_nil t
.errors
.on(:title)
624 def test_validate_format_with_formatted_message
625 Topic
.validates_format_of(:title, :with => /^Valid Title$/, :message => "can't be {{value}}")
626 t
= Topic
.create(:title => 'Invalid title')
627 assert_equal
"can't be Invalid title", t
.errors
.on(:title)
630 def test_validates_inclusion_of
631 Topic
.validates_inclusion_of( :title, :in => %w( a b c d e f g
) )
633 assert
!Topic
.create("title" => "a!", "content" => "abc").valid
?
634 assert
!Topic
.create("title" => "a b", "content" => "abc").valid
?
635 assert
!Topic
.create("title" => nil, "content" => "def").valid
?
637 t
= Topic
.create("title" => "a", "content" => "I know you are but what am I?")
641 assert t
.errors
.on(:title)
642 assert_equal
"is not included in the list", t
.errors
["title"]
644 assert_raise(ArgumentError
) { Topic
.validates_inclusion_of( :title, :in => nil ) }
645 assert_raise(ArgumentError
) { Topic
.validates_inclusion_of( :title, :in => 0) }
647 assert_nothing_raised(ArgumentError
) { Topic
.validates_inclusion_of( :title, :in => "hi!" ) }
648 assert_nothing_raised(ArgumentError
) { Topic
.validates_inclusion_of( :title, :in => {} ) }
649 assert_nothing_raised(ArgumentError
) { Topic
.validates_inclusion_of( :title, :in => [] ) }
652 def test_validates_inclusion_of_with_allow_nil
653 Topic
.validates_inclusion_of( :title, :in => %w( a b c d e f g
), :allow_nil=>true )
655 assert
!Topic
.create("title" => "a!", "content" => "abc").valid
?
656 assert
!Topic
.create("title" => "", "content" => "abc").valid
?
657 assert Topic
.create("title" => nil, "content" => "abc").valid
?
660 def test_numericality_with_getter_method
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
?
669 def test_validates_length_of_with_allow_nil
670 Topic
.validates_length_of( :title, :is => 5, :allow_nil=>true )
672 assert
!Topic
.create("title" => "ab").valid
?
673 assert
!Topic
.create("title" => "").valid
?
674 assert Topic
.create("title" => nil).valid
?
675 assert Topic
.create("title" => "abcde").valid
?
678 def test_validates_length_of_with_allow_blank
679 Topic
.validates_length_of( :title, :is => 5, :allow_blank=>true )
681 assert
!Topic
.create("title" => "ab").valid
?
682 assert Topic
.create("title" => "").valid
?
683 assert Topic
.create("title" => nil).valid
?
684 assert Topic
.create("title" => "abcde").valid
?
687 def test_validates_inclusion_of_with_formatted_message
688 Topic
.validates_inclusion_of( :title, :in => %w( a b c d e f g
), :message => "option {{value}} is not in the list" )
690 assert Topic
.create("title" => "a", "content" => "abc").valid
?
692 t
= Topic
.create("title" => "uhoh", "content" => "abc")
694 assert t
.errors
.on(:title)
695 assert_equal
"option uhoh is not in the list", t
.errors
["title"]
698 def test_numericality_with_allow_nil_and_getter_method
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
?
707 def test_validates_exclusion_of
708 Topic
.validates_exclusion_of( :title, :in => %w( abe monkey
) )
710 assert Topic
.create("title" => "something", "content" => "abc").valid
?
711 assert
!Topic
.create("title" => "monkey", "content" => "abc").valid
?
714 def test_validates_exclusion_of_with_formatted_message
715 Topic
.validates_exclusion_of( :title, :in => %w( abe monkey
), :message => "option {{value}} is restricted" )
717 assert Topic
.create("title" => "something", "content" => "abc")
719 t
= Topic
.create("title" => "monkey")
721 assert t
.errors
.on(:title)
722 assert_equal
"option monkey is restricted", t
.errors
["title"]
725 def test_validates_length_of_using_minimum
726 Topic
.validates_length_of
:title, :minimum => 5
728 t
= Topic
.create("title" => "valid", "content" => "whatever")
733 assert t
.errors
.on(:title)
734 assert_equal
"is too short (minimum is 5 characters)", t
.errors
["title"]
738 assert t
.errors
.on(:title)
739 assert_equal
"is too short (minimum is 5 characters)", t
.errors
["title"]
743 assert t
.errors
.on(:title)
744 assert_equal
"is too short (minimum is 5 characters)", t
.errors
["title"]
747 def test_optionally_validates_length_of_using_minimum
748 Topic
.validates_length_of
:title, :minimum => 5, :allow_nil => true
750 t
= Topic
.create("title" => "valid", "content" => "whatever")
757 def test_validates_length_of_using_maximum
758 Topic
.validates_length_of
:title, :maximum => 5
760 t
= Topic
.create("title" => "valid", "content" => "whatever")
765 assert t
.errors
.on(:title)
766 assert_equal
"is too long (maximum is 5 characters)", t
.errors
["title"]
775 def test_optionally_validates_length_of_using_maximum
776 Topic
.validates_length_of
:title, :maximum => 5, :allow_nil => true
778 t
= Topic
.create("title" => "valid", "content" => "whatever")
785 def test_validates_length_of_using_within
786 Topic
.validates_length_of(:title, :content, :within => 3..5)
788 t
= Topic
.new("title" => "a!", "content" => "I'm ooooooooh so very long")
790 assert_equal
"is too short (minimum is 3 characters)", t
.errors
.on(:title)
791 assert_equal
"is too long (maximum is 5 characters)", t
.errors
.on(:content)
796 assert_equal
"is too short (minimum is 3 characters)", t
.errors
.on(:title)
797 assert_equal
"is too short (minimum is 3 characters)", t
.errors
.on(:content)
804 def test_optionally_validates_length_of_using_within
805 Topic
.validates_length_of
:title, :content, :within => 3..5, :allow_nil => true
807 t
= Topic
.create('title' => 'abc', 'content' => 'abcd')
814 def test_optionally_validates_length_of_using_within_on_create
815 Topic
.validates_length_of
:title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: {{count}}"
817 t
= Topic
.create("title" => "thisisnotvalid", "content" => "whatever")
819 assert t
.errors
.on(:title)
820 assert_equal
"my string is too long: 10", t
.errors
[:title]
822 t
.title
= "butthisis"
828 t
.content
= "andthisislong"
831 t
.content
= t
.title
= "iamfine"
835 def test_optionally_validates_length_of_using_within_on_update
836 Topic
.validates_length_of
:title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: {{count}}"
838 t
= Topic
.create("title" => "vali", "content" => "whatever")
840 assert t
.errors
.on(:title)
844 assert t
.errors
.on(:title)
845 assert_equal
"my string is too short: 5", t
.errors
[:title]
848 t
.content
= "andthisistoolong"
850 assert t
.errors
.on(:content)
852 t
.content
= "iamfine"
856 def test_validates_length_of_using_is
857 Topic
.validates_length_of
:title, :is => 5
859 t
= Topic
.create("title" => "valid", "content" => "whatever")
864 assert t
.errors
.on(:title)
865 assert_equal
"is the wrong length (should be 5 characters)", t
.errors
["title"]
874 def test_optionally_validates_length_of_using_is
875 Topic
.validates_length_of
:title, :is => 5, :allow_nil => true
877 t
= Topic
.create("title" => "valid", "content" => "whatever")
884 def test_validates_length_of_using_bignum
887 bigrange
= bigmin
...bigmax
888 assert_nothing_raised
do
889 Topic
.validates_length_of
:title, :is => bigmin
+ 5
890 Topic
.validates_length_of
:title, :within => bigrange
891 Topic
.validates_length_of
:title, :in => bigrange
892 Topic
.validates_length_of
:title, :minimum => bigmin
893 Topic
.validates_length_of
:title, :maximum => bigmax
897 def test_validates_length_with_globally_modified_error_message
898 ActiveSupport
::Deprecation.silence
do
899 ActiveRecord
::Errors.default_error_messages
[:too_short] = 'tu est trops petit hombre {{count}}'
901 Topic
.validates_length_of
:title, :minimum => 10
902 t
= Topic
.create(:title => 'too short')
905 assert_equal
'tu est trops petit hombre 10', t
.errors
['title']
908 def test_validates_size_of_association
909 repair_validations(Owner
) do
910 assert_nothing_raised
{ Owner
.validates_size_of
:pets, :minimum => 1 }
911 o
= Owner
.new('name' => 'nopets')
913 assert o
.errors
.on(:pets)
914 pet
= o
.pets
.build('name' => 'apet')
919 def test_validates_size_of_association_using_within
920 repair_validations(Owner
) do
921 assert_nothing_raised
{ Owner
.validates_size_of
:pets, :within => 1..2 }
922 o
= Owner
.new('name' => 'nopets')
924 assert o
.errors
.on(:pets)
926 pet
= o
.pets
.build('name' => 'apet')
929 2.times
{ o
.pets
.build('name' => 'apet') }
931 assert o
.errors
.on(:pets)
935 def test_validates_length_of_nasty_params
936 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :minimum=>6, :maximum=>9) }
937 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :within=>6, :maximum=>9) }
938 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :within=>6, :minimum=>9) }
939 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :within=>6, :is=>9) }
940 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :minimum=>"a") }
941 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :maximum=>"a") }
942 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :within=>"a") }
943 assert_raise(ArgumentError
) { Topic
.validates_length_of(:title, :is=>"a") }
946 def test_validates_length_of_custom_errors_for_minimum_with_message
947 Topic
.validates_length_of( :title, :minimum=>5, :message=>"boo {{count}}" )
948 t
= Topic
.create("title" => "uhoh", "content" => "whatever")
950 assert t
.errors
.on(:title)
951 assert_equal
"boo 5", t
.errors
["title"]
954 def test_validates_length_of_custom_errors_for_minimum_with_too_short
955 Topic
.validates_length_of( :title, :minimum=>5, :too_short=>"hoo {{count}}" )
956 t
= Topic
.create("title" => "uhoh", "content" => "whatever")
958 assert t
.errors
.on(:title)
959 assert_equal
"hoo 5", t
.errors
["title"]
962 def test_validates_length_of_custom_errors_for_maximum_with_message
963 Topic
.validates_length_of( :title, :maximum=>5, :message=>"boo {{count}}" )
964 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
966 assert t
.errors
.on(:title)
967 assert_equal
"boo 5", t
.errors
["title"]
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")
974 assert t
.errors
.on(:title)
975 assert_equal
"hoo 10", t
.errors
["title"]
977 t
= Topic
.create("title" => "uhohuhohuhohuhohuhohuhohuhohuhoh", "content" => "whatever")
979 assert t
.errors
.on(:title)
980 assert_equal
"hoo 20", t
.errors
["title"]
983 def test_validates_length_of_custom_errors_for_maximum_with_too_long
984 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}" )
985 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
987 assert t
.errors
.on(:title)
988 assert_equal
"hoo 5", t
.errors
["title"]
991 def test_validates_length_of_custom_errors_for_is_with_message
992 Topic
.validates_length_of( :title, :is=>5, :message=>"boo {{count}}" )
993 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
995 assert t
.errors
.on(:title)
996 assert_equal
"boo 5", t
.errors
["title"]
999 def test_validates_length_of_custom_errors_for_is_with_wrong_length
1000 Topic
.validates_length_of( :title, :is=>5, :wrong_length=>"hoo {{count}}" )
1001 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1003 assert t
.errors
.on(:title)
1004 assert_equal
"hoo 5", t
.errors
["title"]
1007 def test_validates_length_of_using_minimum_utf8
1008 with_kcode('UTF8') do
1009 Topic
.validates_length_of
:title, :minimum => 5
1011 t
= Topic
.create("title" => "一二三四五", "content" => "whatever")
1016 assert t
.errors
.on(:title)
1017 assert_equal
"is too short (minimum is 5 characters)", t
.errors
["title"]
1021 def test_validates_length_of_using_maximum_utf8
1022 with_kcode('UTF8') do
1023 Topic
.validates_length_of
:title, :maximum => 5
1025 t
= Topic
.create("title" => "一二三四五", "content" => "whatever")
1030 assert t
.errors
.on(:title)
1031 assert_equal
"is too long (maximum is 5 characters)", t
.errors
["title"]
1035 def test_validates_length_of_using_within_utf8
1036 with_kcode('UTF8') do
1037 Topic
.validates_length_of(:title, :content, :within => 3..5)
1039 t
= Topic
.new("title" => "一二", "content" => "12三四五六七")
1041 assert_equal
"is too short (minimum is 3 characters)", t
.errors
.on(:title)
1042 assert_equal
"is too long (maximum is 5 characters)", t
.errors
.on(:content)
1049 def test_optionally_validates_length_of_using_within_utf8
1050 with_kcode('UTF8') do
1051 Topic
.validates_length_of
:title, :within => 3..5, :allow_nil => true
1053 t
= Topic
.create(:title => "一二三四五")
1054 assert t
.valid
?, t
.errors
.inspect
1056 t
= Topic
.create(:title => "一二三")
1057 assert t
.valid
?, t
.errors
.inspect
1060 assert t
.valid
?, t
.errors
.inspect
1064 def test_optionally_validates_length_of_using_within_on_create_utf8
1065 with_kcode('UTF8') do
1066 Topic
.validates_length_of
:title, :within => 5..10, :on => :create, :too_long => "長すぎます: {{count}}"
1068 t
= Topic
.create("title" => "一二三四五六七八九十A", "content" => "whatever")
1070 assert t
.errors
.on(:title)
1071 assert_equal
"長すぎます: 10", t
.errors
[:title]
1073 t
.title
= "一二三四五六七八九"
1079 t
.content
= "一二三四五六七八九十"
1082 t
.content
= t
.title
= "一二三四五六"
1087 def test_optionally_validates_length_of_using_within_on_update_utf8
1088 with_kcode('UTF8') do
1089 Topic
.validates_length_of
:title, :within => 5..10, :on => :update, :too_short => "短すぎます: {{count}}"
1091 t
= Topic
.create("title" => "一二三4", "content" => "whatever")
1093 assert t
.errors
.on(:title)
1097 assert t
.errors
.on(:title)
1098 assert_equal
"短すぎます: 5", t
.errors
[:title]
1100 t
.title
= "一二三四五六七八九十A"
1102 assert t
.errors
.on(:title)
1109 def test_validates_length_of_using_is_utf8
1110 with_kcode('UTF8') do
1111 Topic
.validates_length_of
:title, :is => 5
1113 t
= Topic
.create("title" => "一二345", "content" => "whatever")
1118 assert t
.errors
.on(:title)
1119 assert_equal
"is the wrong length (should be 5 characters)", t
.errors
["title"]
1123 def test_validates_length_of_with_block
1124 Topic
.validates_length_of
:content, :minimum => 5, :too_short=>"Your essay must be at least {{count}} words.",
1125 :tokenizer => lambda
{|str
| str
.scan(/\w+/) }
1126 t
= Topic
.create
!(:content => "this content should be long enough")
1129 t
.content
= "not long enough"
1131 assert t
.errors
.on(:content)
1132 assert_equal
"Your essay must be at least 5 words.", t
.errors
[:content]
1135 def test_validates_size_of_association_utf8
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' => 'あいうえおかきくけこ')
1141 assert o
.errors
.on(:pets)
1142 o
.pets
.build('name' => 'あいうえおかきくけこ')
1148 def test_validates_associated_many
1149 Topic
.validates_associated( :replies )
1150 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1151 t
.replies
<< [r
= Reply
.new("title" => "A reply"), r2
= Reply
.new("title" => "Another reply", "content" => "non-empty"), r3
= Reply
.new("title" => "Yet another reply"), r4
= Reply
.new("title" => "The last reply", "content" => "non-empty")]
1153 assert t
.errors
.on(:replies)
1154 assert_equal
1, r
.errors
.count
# make sure all associated objects have been validated
1155 assert_equal
0, r2
.errors
.count
1156 assert_equal
1, r3
.errors
.count
1157 assert_equal
0, r4
.errors
.count
1158 r
.content
= r3
.content
= "non-empty"
1162 def test_validates_associated_one
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")
1169 assert r
.errors
.on(:topic)
1170 r
.topic
.content
= "non-empty"
1175 def test_validate_block
1176 Topic
.validate
{ |topic
| topic
.errors
.add("title", "will never be valid") }
1177 t
= Topic
.create("title" => "Title", "content" => "whatever")
1179 assert t
.errors
.on(:title)
1180 assert_equal
"will never be valid", t
.errors
["title"]
1183 def test_invalid_validator
1185 assert_raise(ArgumentError
) { t
= Topic
.create
}
1188 def test_throw_away_typing
1189 d
= Developer
.new("name" => "David", "salary" => "100,000")
1191 assert_equal
100, d
.salary
1192 assert_equal
"100,000", d
.salary_before_type_cast
1195 def test_validates_acceptance_of_with_custom_error_using_quotes
1196 repair_validations(Developer
) do
1197 Developer
.validates_acceptance_of
:salary, :message=> "This string contains 'single' and \"double\" quotes"
1201 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:salary).last
1205 def test_validates_confirmation_of_with_custom_error_using_quotes
1206 repair_validations(Developer
) do
1207 Developer
.validates_confirmation_of
:name, :message=> "confirm 'single' and \"double\" quotes"
1210 d
.name_confirmation
= "Johnny"
1212 assert_equal
"confirm 'single' and \"double\" quotes", d
.errors
.on(:name)
1216 def test_validates_format_of_with_custom_error_using_quotes
1217 repair_validations(Developer
) do
1218 Developer
.validates_format_of
:name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
1220 d
.name
= d
.name_confirmation
= "John 32"
1222 assert_equal
"format 'single' and \"double\" quotes", d
.errors
.on(:name)
1226 def test_validates_inclusion_of_with_custom_error_using_quotes
1227 repair_validations(Developer
) do
1228 Developer
.validates_inclusion_of
:salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes"
1232 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:salary).last
1236 def test_validates_length_of_with_custom_too_long_using_quotes
1237 repair_validations(Developer
) do
1238 Developer
.validates_length_of
:name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes"
1242 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:name)
1246 def test_validates_length_of_with_custom_too_short_using_quotes
1247 repair_validations(Developer
) do
1248 Developer
.validates_length_of
:name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes"
1252 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:name)
1256 def test_validates_length_of_with_custom_message_using_quotes
1257 repair_validations(Developer
) do
1258 Developer
.validates_length_of
:name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes"
1262 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:name)
1266 def test_validates_presence_of_with_custom_message_using_quotes
1267 repair_validations(Developer
) do
1268 Developer
.validates_presence_of
:non_existent, :message=> "This string contains 'single' and \"double\" quotes"
1272 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:non_existent)
1276 def test_validates_uniqueness_of_with_custom_message_using_quotes
1277 repair_validations(Developer
) do
1278 Developer
.validates_uniqueness_of
:name, :message=> "This string contains 'single' and \"double\" quotes"
1282 assert_equal
"This string contains 'single' and \"double\" quotes", d
.errors
.on(:name)
1286 def test_validates_associated_with_custom_message_using_quotes
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")
1293 assert_equal
"This string contains 'single' and \"double\" quotes", r
.errors
.on(:topic)
1297 def test_if_validation_using_method_true
1298 # When the method returns true
1299 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :if => :condition_is_true )
1300 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1302 assert t
.errors
.on(:title)
1303 assert_equal
"hoo 5", t
.errors
["title"]
1306 def test_unless_validation_using_method_true
1307 # When the method returns true
1308 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :unless => :condition_is_true )
1309 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1311 assert
!t
.errors
.on(:title)
1314 def test_if_validation_using_method_false
1315 # When the method returns false
1316 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :if => :condition_is_true_but_its_not )
1317 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1319 assert
!t
.errors
.on(:title)
1322 def test_unless_validation_using_method_false
1323 # When the method returns false
1324 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :unless => :condition_is_true_but_its_not )
1325 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1327 assert t
.errors
.on(:title)
1328 assert_equal
"hoo 5", t
.errors
["title"]
1331 def test_if_validation_using_string_true
1332 # When the evaluated string returns true
1333 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :if => "a = 1; a == 1" )
1334 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1336 assert t
.errors
.on(:title)
1337 assert_equal
"hoo 5", t
.errors
["title"]
1340 def test_unless_validation_using_string_true
1341 # When the evaluated string returns true
1342 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :unless => "a = 1; a == 1" )
1343 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1345 assert
!t
.errors
.on(:title)
1348 def test_if_validation_using_string_false
1349 # When the evaluated string returns false
1350 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :if => "false")
1351 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1353 assert
!t
.errors
.on(:title)
1356 def test_unless_validation_using_string_false
1357 # When the evaluated string returns false
1358 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}", :unless => "false")
1359 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1361 assert t
.errors
.on(:title)
1362 assert_equal
"hoo 5", t
.errors
["title"]
1365 def test_if_validation_using_block_true
1366 # When the block returns true
1367 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}",
1368 :if => Proc
.new
{ |r
| r
.content
.size
> 4 } )
1369 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1371 assert t
.errors
.on(:title)
1372 assert_equal
"hoo 5", t
.errors
["title"]
1375 def test_unless_validation_using_block_true
1376 # When the block returns true
1377 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}",
1378 :unless => Proc
.new
{ |r
| r
.content
.size
> 4 } )
1379 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1381 assert
!t
.errors
.on(:title)
1384 def test_if_validation_using_block_false
1385 # When the block returns false
1386 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}",
1387 :if => Proc
.new
{ |r
| r
.title
!= "uhohuhoh"} )
1388 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1390 assert
!t
.errors
.on(:title)
1393 def test_unless_validation_using_block_false
1394 # When the block returns false
1395 Topic
.validates_length_of( :title, :maximum=>5, :too_long=>"hoo {{count}}",
1396 :unless => Proc
.new
{ |r
| r
.title
!= "uhohuhoh"} )
1397 t
= Topic
.create("title" => "uhohuhoh", "content" => "whatever")
1399 assert t
.errors
.on(:title)
1400 assert_equal
"hoo 5", t
.errors
["title"]
1403 def test_validates_associated_missing
1404 repair_validations(Reply
) do
1405 Reply
.validates_presence_of(:topic)
1406 r
= Reply
.create("title" => "A reply", "content" => "with content!")
1408 assert r
.errors
.on(:topic)
1410 r
.topic
= Topic
.find
:first
1415 def test_errors_to_xml
1416 r
= Reply
.new
:title => "Wrong Create"
1418 xml
= r
.errors
.to_xml(:skip_instruct => true)
1419 assert_equal
"<errors>", xml
.first(8)
1420 assert xml
.include?("<error>Title is Wrong Create</error>")
1421 assert xml
.include?("<error>Content Empty</error>")
1424 def test_validation_order
1425 Topic
.validates_presence_of
:title
1426 Topic
.validates_length_of
:title, :minimum => 2
1428 t
= Topic
.new("title" => "")
1430 assert_equal
"can't be blank", t
.errors
.on("title").first
1433 def test_invalid_should_be_the_opposite_of_valid
1434 Topic
.validates_presence_of
:title
1438 assert t
.errors
.invalid
?(:title)
1440 t
.title
= 'Things are going to change'
1444 # previous implementation of validates_presence_of eval'd the
1445 # string with the wrong binding, this regression test is to
1446 # ensure that it works correctly
1447 def test_validation_with_if_as_string
1448 Topic
.validates_presence_of(:title)
1449 Topic
.validates_presence_of(:author_name, :if => "title.to_s.match('important')")
1452 assert
!t
.valid
?, "A topic without a title should not be valid"
1453 assert
!t
.errors
.invalid
?("author_name"), "A topic without an 'important' title should not require an author"
1455 t
.title
= "Just a title"
1456 assert t
.valid
?, "A topic with a basic title should be valid"
1458 t
.title
= "A very important title"
1459 assert
!t
.valid
?, "A topic with an important title, but without an author, should not be valid"
1460 assert t
.errors
.invalid
?("author_name"), "A topic with an 'important' title should require an author"
1462 t
.author_name
= "Hubert J. Farnsworth"
1463 assert t
.valid
?, "A topic with an important title and author should be valid"
1468 class ValidatesNumericalityTest
< ActiveRecord
::TestCase
1470 BLANK
= ["", " ", " \t \r \n"]
1471 BIGDECIMAL_STRINGS
= %w(12345678901234567890.1234567890) # 30 significent digits
1472 FLOAT_STRINGS
= %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1
-90.1e5
-90.1e-5 90e-5)
1473 INTEGER_STRINGS
= %w(0 +0 -0 10 +10 -10 0090 -090)
1474 FLOATS
= [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
1475 INTEGERS
= [0, 10, -10] + INTEGER_STRINGS
1476 BIGDECIMAL
= BIGDECIMAL_STRINGS
.collect
! { |bd
| BigDecimal
.new(bd
) }
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"]
1478 INFINITY
= [1.0/0.0]
1480 repair_validations(Topic
)
1482 def test_default_validates_numericality_of
1483 Topic
.validates_numericality_of
:approved
1485 invalid
!(NIL + BLANK
+ JUNK
)
1486 valid
!(FLOATS
+ INTEGERS
+ BIGDECIMAL
+ INFINITY
)
1489 def test_validates_numericality_of_with_nil_allowed
1490 Topic
.validates_numericality_of
:approved, :allow_nil => true
1493 valid
!(NIL + BLANK
+ FLOATS
+ INTEGERS
+ BIGDECIMAL
+ INFINITY
)
1496 def test_validates_numericality_of_with_integer_only
1497 Topic
.validates_numericality_of
:approved, :only_integer => true
1499 invalid
!(NIL + BLANK
+ JUNK
+ FLOATS
+ BIGDECIMAL
+ INFINITY
)
1503 def test_validates_numericality_of_with_integer_only_and_nil_allowed
1504 Topic
.validates_numericality_of
:approved, :only_integer => true, :allow_nil => true
1506 invalid
!(JUNK
+ FLOATS
+ BIGDECIMAL
+ INFINITY
)
1507 valid
!(NIL + BLANK
+ INTEGERS
)
1510 def test_validates_numericality_with_greater_than
1511 Topic
.validates_numericality_of
:approved, :greater_than => 10
1513 invalid
!([-10, 10], 'must be greater than 10')
1517 def test_validates_numericality_with_greater_than_or_equal
1518 Topic
.validates_numericality_of
:approved, :greater_than_or_equal_to => 10
1520 invalid
!([-9, 9], 'must be greater than or equal to 10')
1524 def test_validates_numericality_with_equal_to
1525 Topic
.validates_numericality_of
:approved, :equal_to => 10
1527 invalid
!([-10, 11] + INFINITY
, 'must be equal to 10')
1531 def test_validates_numericality_with_less_than
1532 Topic
.validates_numericality_of
:approved, :less_than => 10
1534 invalid
!([10], 'must be less than 10')
1538 def test_validates_numericality_with_less_than_or_equal_to
1539 Topic
.validates_numericality_of
:approved, :less_than_or_equal_to => 10
1541 invalid
!([11], 'must be less than or equal to 10')
1545 def test_validates_numericality_with_odd
1546 Topic
.validates_numericality_of
:approved, :odd => true
1548 invalid
!([-2, 2], 'must be odd')
1552 def test_validates_numericality_with_even
1553 Topic
.validates_numericality_of
:approved, :even => true
1555 invalid
!([-1, 1], 'must be even')
1559 def test_validates_numericality_with_greater_than_less_than_and_even
1560 Topic
.validates_numericality_of
:approved, :greater_than => 1, :less_than => 4, :even => true
1566 def test_validates_numericality_with_numeric_message
1567 Topic
.validates_numericality_of
:approved, :less_than => 4, :message => "smaller than {{count}}"
1568 topic
= Topic
.new("title" => "numeric test", "approved" => 10)
1570 assert
!topic
.valid
?
1571 assert_equal
"smaller than 4", topic
.errors
.on(:approved)
1573 Topic
.validates_numericality_of
:approved, :greater_than => 4, :message => "greater than {{count}}"
1574 topic
= Topic
.new("title" => "numeric test", "approved" => 1)
1576 assert
!topic
.valid
?
1577 assert_equal
"greater than 4", topic
.errors
.on(:approved)
1581 def invalid
!(values
, error
=nil)
1582 with_each_topic_approved_value(values
) do |topic
, value
|
1583 assert
!topic
.valid
?, "#{value.inspect} not rejected as a number"
1584 assert topic
.errors
.on(:approved)
1585 assert_equal error
, topic
.errors
.on(:approved) if error
1590 with_each_topic_approved_value(values
) do |topic
, value
|
1591 assert topic
.valid
?, "#{value.inspect} not accepted as a number"
1595 def with_each_topic_approved_value(values
)
1596 topic
= Topic
.new("title" => "numeric test", "content" => "whatever")
1597 values
.each
do |value
|
1598 topic
.approved
= value