1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activerecord/test/cases/validations_test.rb

230 lines
6.7 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
require "cases/helper"
require "models/topic"
require "models/reply"
require "models/developer"
require "models/computer"
require "models/parrot"
require "models/company"
require "models/price_estimate"
class ValidationsTest < ActiveRecord::TestCase
fixtures :topics, :developers
# Most of the tests mess with the validations of Topic, so lets repair it all the time.
# Other classes we mess with will be dealt with in the specific tests
repair_validations(Topic)
def test_valid_uses_create_context_when_new
r = WrongReply.new
r.title = "Wrong Create"
assert_not_predicate 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
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
def test_valid_using_special_context
2016-08-06 13:37:57 -04:00
r = WrongReply.new(title: "Valid title")
assert_not r.valid?(:special_case)
2010-05-21 10:20:56 -04:00
assert_equal "Invalid", r.errors[:author_name].join
2010-05-21 10:20:56 -04:00
r.author_name = "secret"
r.content = "Good"
assert r.valid?(:special_case)
2010-05-21 10:20:56 -04:00
r.author_name = nil
assert_not r.valid?(:special_case)
2010-05-21 10:20:56 -04:00
assert_equal "Invalid", r.errors[:author_name].join
2010-05-21 10:20:56 -04:00
r.author_name = "secret"
assert r.valid?(:special_case)
end
def test_invalid_using_multiple_contexts
2016-08-06 13:37:57 -04:00
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
def test_validate
r = WrongReply.new
r.validate
assert_empty r.errors[:author_name]
r.validate(:special_case)
assert_not_empty r.errors[:author_name]
r.author_name = "secret"
r.validate(:special_case)
assert_empty r.errors[:author_name]
end
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
def test_validate_with_bang
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.new.validate!
end
end
def test_validate_with_bang_and_context
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.new.validate!(:special_case)
end
2016-08-06 13:37:57 -04:00
r = WrongReply.new(title: "Valid title", author_name: "secret", content: "Good")
assert r.validate!(:special_case)
end
def test_exception_on_create_bang_many
assert_raise(ActiveRecord::RecordInvalid) do
WrongReply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
end
end
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
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
def test_save_without_validation
reply = WrongReply.new
assert_not reply.save
2016-08-06 13:37:57 -04:00
assert reply.save(validate: false)
end
2013-11-30 09:57:01 -05:00
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
def test_throw_away_typing
d = Developer.new("name" => "David", "salary" => "100,000")
assert_not_predicate d, :valid?
assert_equal 100, d.salary
assert_equal "100,000", d.salary_before_type_cast
end
def test_validates_acceptance_of_with_undefined_attribute_methods
klass = Class.new(Topic)
klass.validates_acceptance_of(:approved)
topic = klass.new(approved: true)
klass.undefine_attribute_methods
assert topic.approved
end
def test_validates_acceptance_of_as_database_column
klass = Class.new(Topic)
klass.validates_acceptance_of(:approved)
topic = klass.create("approved" => true)
assert topic["approved"]
end
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
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_predicate topic, :valid?
end
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
Suppress `warning: BigDecimal.new is deprecated` in activerecord `BigDecimal.new` has been deprecated in BigDecimal 1.3.3 which will be a default for Ruby 2.5. Refer https://github.com/ruby/bigdecimal/commit/533737338db915b00dc7168c3602e4b462b23503 ``` $ cd rails/activerecord/ $ git grep -l BigDecimal.new | grep \.rb | xargs sed -i -e "s/BigDecimal.new/BigDecimal/g" ``` - Changes made only to Active Record. Will apply the same change to other module once this commit is merged. - The following deprecation has not been addressed because it has been reported at `ActiveRecord::Result.new`. `ActiveRecord::Result.ancestors` did not show `BigDecimal`. * Not addressed ```ruby /path/to/rails/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb:34: warning: BigDecimal.new is deprecated ``` * database_statements.rb:34 ```ruby ActiveRecord::Result.new(result.fields, result.to_a) if result ``` * ActiveRecord::Result.ancestors ```ruby [ActiveRecord::Result, Enumerable, ActiveSupport::ToJsonWithActiveSupportEncoder, Object, Metaclass::ObjectMethods, Mocha::ObjectMethods, PP::ObjectMixin, ActiveSupport::Dependencies::Loadable, ActiveSupport::Tryable, JSON::Ext::Generator::GeneratorMethods::Object, Kernel, BasicObject] ``` This commit has been tested with these Ruby and BigDecimal versions - ruby 2.5 and bigdecimal 1.3.3 ``` $ ruby -v ruby 2.5.0dev (2017-12-14 trunk 61217) [x86_64-linux] $ gem list |grep bigdecimal bigdecimal (default: 1.3.3, default: 1.3.2) ``` - ruby 2.4 and bigdecimal 1.3.0 ``` $ ruby -v ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux-gnu] $ gem list |grep bigdecimal bigdecimal (default: 1.3.0) ``` - ruby 2.3 and bigdecimal 1.2.8 ``` $ ruby -v ruby 2.3.5p376 (2017-09-14 revision 59905) [x86_64-linux] $ gem list |grep -i bigdecimal bigdecimal (1.2.8) ``` - ruby 2.2 and bigdecimal 1.2.6 ``` $ ruby -v ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-linux] $ gem list |grep bigdecimal bigdecimal (1.2.6) ```
2017-12-13 14:46:46 -05:00
validates_numericality_of :wibble, greater_than_or_equal_to: BigDecimal("97.18")
end
["97.179", 97.179, BigDecimal("97.179")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal BigDecimal("97.18"), subject.wibble
assert_predicate subject, :valid?
end
["97.174", 97.174, BigDecimal("97.174")].each do |raw_value|
subject = klass.new(wibble: raw_value)
assert_equal BigDecimal("97.17"), subject.wibble
assert_not_predicate subject, :valid?
end
end
def test_numericality_validator_wont_be_affected_by_custom_getter
price_estimate = PriceEstimate.new(price: 50)
assert_equal "$50.00", price_estimate.price
assert_equal 50, price_estimate.price_before_type_cast
assert_equal 50, price_estimate.read_attribute(:price)
assert_predicate price_estimate, :price_came_from_user?
assert_predicate price_estimate, :valid?
price_estimate.save!
assert_not_predicate price_estimate, :price_came_from_user?
assert_predicate price_estimate, :valid?
end
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
end