class ValidationsTest
Public Class Methods
model_name()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 174 def self.model_name ActiveModel::Name.new(self, nil, "Topic") end
new(*)
click to toggle source
Calls superclass method
# File activemodel/test/cases/validations_test.rb, line 183 def initialize(*) super @call_sequence = [] end
Public Instance Methods
teardown()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 15 def teardown Topic.clear_validators! end
test_acceptance_validator_doesnt_require_db_connection()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 186 def test_acceptance_validator_doesnt_require_db_connection klass = Class.new(ActiveRecord::Base) do self.table_name = "posts" end klass.reset_column_information assert_no_queries do klass.validates_acceptance_of(:foo) end end
test_accessing_instance_of_validator_on_an_attribute()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 306 def test_accessing_instance_of_validator_on_an_attribute Topic.validates_length_of :title, minimum: 10 assert_equal 10, Topic.validators_on(:title).first.options[:minimum] end
test_callback_options_to_validate()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 179 def test_callback_options_to_validate klass = Class.new(Topic) do attr_reader :call_sequence def initialize(*) super @call_sequence = [] end private def validator_a @call_sequence << :a end def validator_b @call_sequence << :b end def validator_c @call_sequence << :c end end assert_nothing_raised do klass.validate :validator_a, if: -> { true } klass.validate :validator_b, prepend: true klass.validate :validator_c, unless: -> { true } end t = klass.new assert_predicate t, :valid? assert_equal [:b, :a], t.call_sequence end
test_does_not_modify_options_argument()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 429 def test_does_not_modify_options_argument options = { presence: true } Topic.validates :title, options assert_equal({ presence: true }, options) end
test_double_attr_validation_and_error_msg()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 39 def test_double_attr_validation_and_error_msg r = Reply.new assert r.invalid? assert r.errors[:title].any?, "A reply without title should mark that attribute as invalid" assert_equal ["is Empty"], r.errors["title"], "A reply without title should contain an error" assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid" assert_equal ["is Empty"], r.errors["content"], "A reply without content should contain an error" assert_equal 2, r.errors.count end
test_dup_validity_is_independent()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 435 def test_dup_validity_is_independent Topic.validates_presence_of :title topic = Topic.new("title" => "Literature") topic.valid? duped = topic.dup duped.title = nil assert duped.invalid? topic.title = nil duped.title = "Mathematics" assert topic.invalid? assert duped.valid? end
test_errors_conversions()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 214 def test_errors_conversions Topic.validates_presence_of %w(title content) t = Topic.new assert t.invalid? xml = t.errors.to_xml assert_match %r{<errors>}, xml assert_match %r{<error>Title can't be blank</error>}, xml assert_match %r{<error>Content can't be blank</error>}, xml hash = {} hash[:title] = ["can't be blank"] hash[:content] = ["can't be blank"] assert_equal t.errors.to_json, hash.to_json end
test_errors_empty_after_errors_on_check()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 112 def test_errors_empty_after_errors_on_check t = Topic.new assert t.errors[:id].empty? assert t.errors.empty? end
test_errors_on_base()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 81 def test_errors_on_base r = Reply.new r.content = "Mismatch" r.valid? r.errors.add(:base, "Reply is not dignifying") errors = r.errors.to_a.inject([]) { |result, error| result + [error] } assert_equal ["Reply is not dignifying"], r.errors[:base] assert_includes errors, "Title is Empty" assert_includes errors, "Reply is not dignifying" assert_equal 2, r.errors.count end
test_errors_on_base_with_symbol_message()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 96 def test_errors_on_base_with_symbol_message r = Reply.new r.content = "Mismatch" r.valid? r.errors.add(:base, :invalid) errors = r.errors.to_a.inject([]) { |result, error| result + [error] } assert_equal ["is invalid"], r.errors[:base] assert_includes errors, "Title is Empty" assert_includes errors, "is invalid" assert_equal 2, r.errors.count end
test_errors_on_nested_attributes_expands_name()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 75 def test_errors_on_nested_attributes_expands_name t = Topic.new t.errors["replies.name"] << "can't be blank" assert_equal ["Replies name can't be blank"], t.errors.full_messages end
test_exception_on_create_bang_many()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 104 def test_exception_on_create_bang_many assert_raise(ActiveRecord::RecordInvalid) do WrongReply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }]) end end
test_exception_on_create_bang_many_with_block()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 118 def test_exception_on_create_bang_many_with_block assert_raise(ActiveRecord::RecordInvalid) do WrongReply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r| r.content = nil end end end
test_exception_on_create_bang_with_block()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 110 def test_exception_on_create_bang_with_block assert_raise(ActiveRecord::RecordInvalid) do WrongReply.create!("title" => "OK") do |r| r.content = nil end end end
test_invalid_options_to_validate()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 170 def test_invalid_options_to_validate error = assert_raises(ArgumentError) do # A common mistake -- we meant to call 'validates' Topic.validate :title, presence: true end message = "Unknown key: :presence. Valid keys are: :on, :if, :unless, :prepend. Perhaps you meant to call `validates` instead of `validate`?" assert_equal message, error.message end
test_invalid_record_exception()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 79 def test_invalid_record_exception assert_raise(ActiveRecord::RecordInvalid) { WrongReply.create! } assert_raise(ActiveRecord::RecordInvalid) { WrongReply.new.save! } r = WrongReply.new invalid = assert_raise ActiveRecord::RecordInvalid do r.save! end assert_equal r, invalid.record end
test_invalid_should_be_the_opposite_of_valid()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 269 def test_invalid_should_be_the_opposite_of_valid Topic.validates_presence_of :title t = Topic.new assert t.invalid? assert t.errors[:title].any? t.title = "Things are going to change" assert !t.invalid? end
test_invalid_using_multiple_contexts()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 57 def test_invalid_using_multiple_contexts r = WrongReply.new(title: "Wrong Create") assert r.invalid?([:special_case, :create]) assert_equal "Invalid", r.errors[:author_name].join assert_equal "is Wrong Create", r.errors[:title].join end
test_invalid_validator()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 162 def test_invalid_validator Topic.validate :i_dont_exist assert_raises(NoMethodError) do t = Topic.new t.valid? end end
test_list_of_validators_for_model()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 288 def test_list_of_validators_for_model Topic.validates_presence_of :title Topic.validates_length_of :title, minimum: 2 assert_equal 2, Topic.validators.count assert_equal [:presence, :length], Topic.validators.map(&:kind) end
test_list_of_validators_on_an_attribute()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 296 def test_list_of_validators_on_an_attribute Topic.validates_presence_of :title, :content Topic.validates_length_of :title, minimum: 2 assert_equal 2, Topic.validators_on(:title).count assert_equal [:presence, :length], Topic.validators_on(:title).map(&:kind) assert_equal 1, Topic.validators_on(:content).count assert_equal [:presence], Topic.validators_on(:content).map(&:kind) end
test_list_of_validators_on_multiple_attributes()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 311 def test_list_of_validators_on_multiple_attributes Topic.validates :title, length: { minimum: 10 } Topic.validates :author_name, presence: true, format: /a/ validators = Topic.validators_on(:title, :author_name) assert_equal [ ActiveModel::Validations::FormatValidator, ActiveModel::Validations::LengthValidator, ActiveModel::Validations::PresenceValidator ], validators.map(&:class).sort_by(&:to_s) end
test_list_of_validators_will_be_empty_when_empty()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 324 def test_list_of_validators_will_be_empty_when_empty Topic.validates :title, length: { minimum: 10 } assert_equal [], Topic.validators_on(:author_name) end
test_multiple_errors_per_attr_iteration_with_full_error_composition()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 62 def test_multiple_errors_per_attr_iteration_with_full_error_composition r = Reply.new r.title = "" r.content = "" r.valid? errors = r.errors.to_a assert_equal "Content is Empty", errors[0] assert_equal "Title is Empty", errors[1] assert_equal 2, r.errors.count end
test_numericality_validation_checks_against_raw_value()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 172 def test_numericality_validation_checks_against_raw_value klass = Class.new(Topic) do def self.model_name ActiveModel::Name.new(self, nil, "Topic") end attribute :wibble, :decimal, scale: 2, precision: 9 validates_numericality_of :wibble, greater_than_or_equal_to: BigDecimal.new("97.18") end assert_not klass.new(wibble: "97.179").valid? assert_not klass.new(wibble: 97.179).valid? assert_not klass.new(wibble: BigDecimal.new("97.179")).valid? end
test_numericality_validation_with_mutation()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 160 def test_numericality_validation_with_mutation klass = Class.new(Topic) do attribute :wibble, :string validates_numericality_of :wibble, only_integer: true end topic = klass.new(wibble: "123-4567") topic.wibble.gsub!("-", "") assert topic.valid? end
test_save_without_validation()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 126 def test_save_without_validation reply = WrongReply.new assert !reply.save assert reply.save(validate: false) end
test_single_attr_validation_and_error_msg()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 30 def test_single_attr_validation_and_error_msg r = Reply.new r.title = "There's no content!" assert r.invalid? assert r.errors[:content].any?, "A reply without content should mark that attribute as invalid" assert_equal ["is Empty"], r.errors["content"], "A reply without content should contain an error" assert_equal 1, r.errors.count end
test_single_error_per_attr_iteration()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 52 def test_single_error_per_attr_iteration r = Reply.new r.valid? errors = r.errors.collect { |attr, messages| [attr.to_s, messages] } assert_includes errors, ["title", "is Empty"] assert_includes errors, ["content", "is Empty"] end
test_single_field_validation()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 19 def test_single_field_validation r = Reply.new r.title = "There's no content!" assert r.invalid?, "A reply without content should be invalid" assert r.after_validation_performed, "after_validation callback should be called" r.content = "Messa content!" assert r.valid?, "A reply with content should be valid" assert r.after_validation_performed, "after_validation callback should be called" end
test_strict_validation_custom_exception()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 401 def test_strict_validation_custom_exception Topic.validates_presence_of :title, strict: CustomStrictValidationException assert_raises CustomStrictValidationException do Topic.new.valid? end end
test_strict_validation_error_message()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 420 def test_strict_validation_error_message Topic.validates :title, strict: true, presence: true exception = assert_raises(ActiveModel::StrictValidationFailed) do Topic.new.valid? end assert_equal "Title can't be blank", exception.message end
test_strict_validation_in_custom_validator_helper()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 394 def test_strict_validation_in_custom_validator_helper Topic.validates_presence_of :title, strict: true assert_raises ActiveModel::StrictValidationFailed do Topic.new.valid? end end
test_strict_validation_in_validates()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 375 def test_strict_validation_in_validates Topic.validates :title, strict: true, presence: true assert_raises ActiveModel::StrictValidationFailed do Topic.new.valid? end end
test_strict_validation_not_fails()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 382 def test_strict_validation_not_fails Topic.validates :title, strict: true, presence: true assert Topic.new(title: "hello").valid? end
test_strict_validation_particular_validator()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 387 def test_strict_validation_particular_validator Topic.validates :title, presence: { strict: true } assert_raises ActiveModel::StrictValidationFailed do Topic.new.valid? end end
test_throw_away_typing()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 140 def test_throw_away_typing d = Developer.new("name" => "David", "salary" => "100,000") assert !d.valid? assert_equal 100, d.salary assert_equal "100,000", d.salary_before_type_cast end
test_valid_uses_create_context_when_new()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 19 def test_valid_uses_create_context_when_new r = WrongReply.new r.title = "Wrong Create" assert_not r.valid? assert r.errors[:title].any?, "A reply with a bad title should mark that attribute as invalid" assert_equal ["is Wrong Create"], r.errors[:title], "A reply with a bad content should contain an error" end
test_valid_uses_update_context_when_persisted()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 27 def test_valid_uses_update_context_when_persisted r = WrongReply.new r.title = "Bad" r.content = "Good" assert r.save, "First validation should be successful" r.title = "Wrong Update" assert_not r.valid?, "Second validation should fail" assert r.errors[:title].any?, "A reply with a bad title should mark that attribute as invalid" assert_equal ["is Wrong Update"], r.errors[:title], "A reply with a bad content should contain an error" end
test_valid_using_special_context()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 40 def test_valid_using_special_context r = WrongReply.new(title: "Valid title") assert !r.valid?(:special_case) assert_equal "Invalid", r.errors[:author_name].join r.author_name = "secret" r.content = "Good" assert r.valid?(:special_case) r.author_name = nil assert_not r.valid?(:special_case) assert_equal "Invalid", r.errors[:author_name].join r.author_name = "secret" assert r.valid?(:special_case) end
test_validate()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 343 def test_validate Topic.validate do validates_presence_of :title, :author_name validates_length_of :content, minimum: 10 end topic = Topic.new assert_empty topic.errors topic.validate assert_not_empty topic.errors end
test_validate_block()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 146 def test_validate_block Topic.validate { errors.add("title", "will never be valid") } t = Topic.new("title" => "Title", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? assert_equal ["will never be valid"], t.errors["title"] end
test_validate_block_with_params()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 154 def test_validate_block_with_params Topic.validate { |topic| topic.errors.add("title", "will never be valid") } t = Topic.new("title" => "Title", "content" => "whatever") assert t.invalid? assert t.errors[:title].any? assert_equal ["will never be valid"], t.errors["title"] end
test_validate_with_bang()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 356 def test_validate_with_bang Topic.validates :title, presence: true assert_raise(ActiveModel::ValidationError) do Topic.new.validate! end end
test_validate_with_bang_and_context()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 364 def test_validate_with_bang_and_context Topic.validates :title, presence: true, on: :context assert_raise(ActiveModel::ValidationError) do Topic.new.validate!(:context) end t = Topic.new(title: "Valid title") assert t.validate!(:context) end
test_validates_acceptance_of_as_database_column()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 147 def test_validates_acceptance_of_as_database_column Topic.validates_acceptance_of(:approved) topic = Topic.create("approved" => true) assert topic["approved"] end
test_validates_acceptance_of_with_non_existent_table()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 132 def test_validates_acceptance_of_with_non_existent_table Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base) assert_nothing_raised do IncorporealModel.validates_acceptance_of(:incorporeal_column) end end
test_validates_each()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 118 def test_validates_each hits = 0 Topic.validates_each(:title, :content, [:title, :content]) do |record, attr| record.errors.add attr, "gotcha" hits += 1 end t = Topic.new("title" => "valid", "content" => "whatever") assert t.invalid? assert_equal 4, hits assert_equal %w(gotcha gotcha), t.errors[:title] assert_equal %w(gotcha gotcha), t.errors[:content] end
test_validates_each_custom_reader()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 131 def test_validates_each_custom_reader hits = 0 CustomReader.validates_each(:title, :content, [:title, :content]) do |record, attr| record.errors.add attr, "gotcha" hits += 1 end t = CustomReader.new("title" => "valid", "content" => "whatever") assert t.invalid? assert_equal 4, hits assert_equal %w(gotcha gotcha), t.errors[:title] assert_equal %w(gotcha gotcha), t.errors[:content] ensure CustomReader.clear_validators! end
test_validates_with_bang()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 408 def test_validates_with_bang Topic.validates! :title, presence: true assert_raises ActiveModel::StrictValidationFailed do Topic.new.valid? end end
test_validates_with_false_hash_value()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 415 def test_validates_with_false_hash_value Topic.validates :title, presence: false assert Topic.new.valid? end
test_validation_order()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 230 def test_validation_order Topic.validates_presence_of :title Topic.validates_length_of :title, minimum: 2 t = Topic.new("title" => "") assert t.invalid? assert_equal "can't be blank", t.errors["title"].first Topic.validates_presence_of :title, :author_name Topic.validate { errors.add("author_email_address", "will never be valid") } Topic.validates_length_of :title, :content, minimum: 2 t = Topic.new title: "" assert t.invalid? assert_equal :title, key = t.errors.keys[0] assert_equal "can't be blank", t.errors[key][0] assert_equal "is too short (minimum is 2 characters)", t.errors[key][1] assert_equal :author_name, key = t.errors.keys[1] assert_equal "can't be blank", t.errors[key][0] assert_equal :author_email_address, key = t.errors.keys[2] assert_equal "will never be valid", t.errors[key][0] assert_equal :content, key = t.errors.keys[3] assert_equal "is too short (minimum is 2 characters)", t.errors[key][0] end
test_validation_with_if_and_on()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 255 def test_validation_with_if_and_on Topic.validates_presence_of :title, if: Proc.new { |x| x.author_name = "bad"; true }, on: :update t = Topic.new(title: "") # If block should not fire assert t.valid? assert t.author_name.nil? # If block should fire assert t.invalid?(:update) assert t.author_name == "bad" end
test_validation_with_message_as_proc()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 280 def test_validation_with_message_as_proc Topic.validates_presence_of(:title, message: proc { "no blanks here".upcase }) t = Topic.new assert t.invalid? assert_equal ["NO BLANKS HERE"], t.errors[:title] end
test_validation_with_message_as_proc_that_takes_a_record_as_a_parameter()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 450 def test_validation_with_message_as_proc_that_takes_a_record_as_a_parameter Topic.validates_presence_of(:title, message: proc { |record| "You have failed me for the last time, #{record.author_name}." }) t = Topic.new(author_name: "Admiral") assert t.invalid? assert_equal ["You have failed me for the last time, Admiral."], t.errors[:title] end
test_validation_with_message_as_proc_that_takes_record_and_data_as_a_parameters()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 458 def test_validation_with_message_as_proc_that_takes_record_and_data_as_a_parameters Topic.validates_presence_of(:title, message: proc { |record, data| "#{data[:attribute]} is missing. You have failed me for the last time, #{record.author_name}." }) t = Topic.new(author_name: "Admiral") assert t.invalid? assert_equal ["Title is missing. You have failed me for the last time, Admiral."], t.errors[:title] end
test_validations_on_the_instance_level()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 329 def test_validations_on_the_instance_level Topic.validates :title, :author_name, presence: true Topic.validates :content, length: { minimum: 10 } topic = Topic.new assert topic.invalid? assert_equal 3, topic.errors.size topic.title = "Some Title" topic.author_name = "Some Author" topic.content = "Some Content Whose Length is more than 10." assert topic.valid? end
test_validators()
click to toggle source
# File activerecord/test/cases/validations_test.rb, line 153 def test_validators assert_equal 1, Parrot.validators.size assert_equal 1, Company.validators.size assert_equal 1, Parrot.validators_on(:name).size assert_equal 1, Company.validators_on(:name).size end
validator_a()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 189 def validator_a @call_sequence << :a end
validator_b()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 193 def validator_b @call_sequence << :b end
validator_c()
click to toggle source
# File activemodel/test/cases/validations_test.rb, line 197 def validator_c @call_sequence << :c end