2017-07-09 13:41:28 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2011-06-06 14:17:44 -04:00
|
|
|
require "cases/helper"
|
2016-08-06 12:26:20 -04:00
|
|
|
require "models/topic"
|
|
|
|
require "models/reply"
|
|
|
|
require "models/developer"
|
|
|
|
require "models/computer"
|
|
|
|
require "models/parrot"
|
|
|
|
require "models/company"
|
2018-08-10 06:42:00 -04:00
|
|
|
require "models/price_estimate"
|
2004-11-23 20:04:44 -05:00
|
|
|
|
2008-01-21 12:20:51 -05:00
|
|
|
class ValidationsTest < ActiveRecord::TestCase
|
2009-03-20 11:07:49 -04:00
|
|
|
fixtures :topics, :developers
|
2004-11-23 20:04:44 -05:00
|
|
|
|
2008-12-19 08:27:34 -05:00
|
|
|
# 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)
|
2004-12-10 08:11:13 -05:00
|
|
|
|
2013-05-17 04:10:37 -04:00
|
|
|
def test_valid_uses_create_context_when_new
|
2009-12-31 21:20:38 -05:00
|
|
|
r = WrongReply.new
|
2004-11-23 20:04:44 -05:00
|
|
|
r.title = "Wrong Create"
|
2018-01-25 18:14:09 -05:00
|
|
|
assert_not_predicate r, :valid?
|
2009-03-21 14:29:15 -04:00
|
|
|
assert r.errors[:title].any?, "A reply with a bad title should mark that attribute as invalid"
|
2009-03-20 13:36:22 -04:00
|
|
|
assert_equal ["is Wrong Create"], r.errors[:title], "A reply with a bad content should contain an error"
|
2004-11-23 20:04:44 -05:00
|
|
|
end
|
|
|
|
|
2013-05-17 04:10:37 -04:00
|
|
|
def test_valid_uses_update_context_when_persisted
|
2009-12-31 21:20:38 -05:00
|
|
|
r = WrongReply.new
|
2004-11-23 20:04:44 -05:00
|
|
|
r.title = "Bad"
|
|
|
|
r.content = "Good"
|
2013-05-17 04:10:37 -04:00
|
|
|
assert r.save, "First validation should be successful"
|
2005-02-18 12:27:26 -05:00
|
|
|
|
2004-11-23 20:04:44 -05:00
|
|
|
r.title = "Wrong Update"
|
2013-05-17 04:10:37 -04:00
|
|
|
assert_not r.valid?, "Second validation should fail"
|
2005-02-18 12:27:26 -05:00
|
|
|
|
2009-03-21 14:29:15 -04:00
|
|
|
assert r.errors[:title].any?, "A reply with a bad title should mark that attribute as invalid"
|
2009-03-20 13:36:22 -04:00
|
|
|
assert_equal ["is Wrong Update"], r.errors[:title], "A reply with a bad content should contain an error"
|
2004-11-23 20:04:44 -05:00
|
|
|
end
|
2005-02-18 12:27:26 -05:00
|
|
|
|
2013-05-17 04:10:37 -04:00
|
|
|
def test_valid_using_special_context
|
2016-08-06 13:37:57 -04:00
|
|
|
r = WrongReply.new(title: "Valid title")
|
2018-04-17 18:21:34 -04:00
|
|
|
assert_not r.valid?(:special_case)
|
2010-05-21 10:20:56 -04:00
|
|
|
assert_equal "Invalid", r.errors[:author_name].join
|
2010-05-10 05:28:38 -04:00
|
|
|
|
2010-05-21 10:20:56 -04:00
|
|
|
r.author_name = "secret"
|
2010-05-10 05:28:38 -04:00
|
|
|
r.content = "Good"
|
|
|
|
assert r.valid?(:special_case)
|
|
|
|
|
2010-05-21 10:20:56 -04:00
|
|
|
r.author_name = nil
|
2013-05-17 04:10:37 -04:00
|
|
|
assert_not r.valid?(:special_case)
|
2010-05-21 10:20:56 -04:00
|
|
|
assert_equal "Invalid", r.errors[:author_name].join
|
2010-05-10 05:28:38 -04:00
|
|
|
|
2010-05-21 10:20:56 -04:00
|
|
|
r.author_name = "secret"
|
2013-05-17 04:10:37 -04:00
|
|
|
assert r.valid?(:special_case)
|
2010-05-10 05:28:38 -04:00
|
|
|
end
|
|
|
|
|
2015-09-07 17:41:50 -04:00
|
|
|
def test_invalid_using_multiple_contexts
|
2016-08-06 13:37:57 -04:00
|
|
|
r = WrongReply.new(title: "Wrong Create")
|
2015-09-07 17:41:50 -04:00
|
|
|
assert r.invalid?([:special_case, :create])
|
|
|
|
assert_equal "Invalid", r.errors[:author_name].join
|
|
|
|
assert_equal "is Wrong Create", r.errors[:title].join
|
|
|
|
end
|
|
|
|
|
2014-03-23 07:09:55 -04:00
|
|
|
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
|
|
|
|
|
2005-04-18 15:19:23 -04:00
|
|
|
def test_invalid_record_exception
|
2009-12-31 21:20:38 -05:00
|
|
|
assert_raise(ActiveRecord::RecordInvalid) { WrongReply.create! }
|
|
|
|
assert_raise(ActiveRecord::RecordInvalid) { WrongReply.new.save! }
|
2005-11-03 13:54:16 -05:00
|
|
|
|
2013-12-19 06:03:39 -05:00
|
|
|
r = WrongReply.new
|
|
|
|
invalid = assert_raise ActiveRecord::RecordInvalid do
|
2005-11-03 13:54:16 -05:00
|
|
|
r.save!
|
|
|
|
end
|
2013-12-19 06:03:39 -05:00
|
|
|
assert_equal r, invalid.record
|
2006-05-18 21:05:20 -04:00
|
|
|
end
|
|
|
|
|
2014-06-23 09:09:40 -04:00
|
|
|
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")
|
2014-06-23 09:09:40 -04:00
|
|
|
assert r.validate!(:special_case)
|
|
|
|
end
|
|
|
|
|
2007-08-28 16:44:51 -04:00
|
|
|
def test_exception_on_create_bang_many
|
2009-03-08 16:11:58 -04:00
|
|
|
assert_raise(ActiveRecord::RecordInvalid) do
|
2009-12-31 21:20:38 -05:00
|
|
|
WrongReply.create!([ { "title" => "OK" }, { "title" => "Wrong Create" }])
|
2007-08-28 16:44:51 -04:00
|
|
|
end
|
|
|
|
end
|
2008-12-19 08:27:34 -05:00
|
|
|
|
2008-05-01 00:14:32 -04:00
|
|
|
def test_exception_on_create_bang_with_block
|
2009-03-08 16:11:58 -04:00
|
|
|
assert_raise(ActiveRecord::RecordInvalid) do
|
2016-08-06 13:44:11 -04:00
|
|
|
WrongReply.create!("title" => "OK") do |r|
|
2008-05-01 00:14:32 -04:00
|
|
|
r.content = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2008-12-19 08:27:34 -05:00
|
|
|
|
2008-05-01 00:14:32 -04:00
|
|
|
def test_exception_on_create_bang_many_with_block
|
2009-03-08 16:11:58 -04:00
|
|
|
assert_raise(ActiveRecord::RecordInvalid) do
|
2009-12-31 21:20:38 -05:00
|
|
|
WrongReply.create!([{ "title" => "OK" }, { "title" => "Wrong Create" }]) do |r|
|
2008-05-01 00:14:32 -04:00
|
|
|
r.content = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2006-12-05 19:13:31 -05:00
|
|
|
|
2013-05-17 04:10:37 -04:00
|
|
|
def test_save_without_validation
|
2009-12-31 21:20:38 -05:00
|
|
|
reply = WrongReply.new
|
2018-04-17 18:21:34 -04:00
|
|
|
assert_not reply.save
|
2016-08-06 13:37:57 -04:00
|
|
|
assert reply.save(validate: false)
|
2010-01-17 08:22:27 -05:00
|
|
|
end
|
|
|
|
|
2013-11-30 09:57:01 -05:00
|
|
|
def test_validates_acceptance_of_with_non_existent_table
|
2007-12-27 06:16:51 -05:00
|
|
|
Object.const_set :IncorporealModel, Class.new(ActiveRecord::Base)
|
|
|
|
|
2016-02-19 23:05:49 -05:00
|
|
|
assert_nothing_raised do
|
2007-12-27 06:16:51 -05:00
|
|
|
IncorporealModel.validates_acceptance_of(:incorporeal_column)
|
|
|
|
end
|
|
|
|
end
|
2007-12-12 18:55:14 -05:00
|
|
|
|
2004-12-19 06:25:55 -05:00
|
|
|
def test_throw_away_typing
|
2006-09-03 13:54:48 -04:00
|
|
|
d = Developer.new("name" => "David", "salary" => "100,000")
|
2018-01-25 18:14:09 -05:00
|
|
|
assert_not_predicate d, :valid?
|
2004-12-19 06:44:59 -05:00
|
|
|
assert_equal 100, d.salary
|
2004-12-19 06:25:55 -05:00
|
|
|
assert_equal "100,000", d.salary_before_type_cast
|
2018-12-17 21:18:18 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_validates_acceptance_of_with_undefined_attribute_methods
|
2019-04-13 09:17:54 -04:00
|
|
|
klass = Class.new(Topic)
|
|
|
|
klass.validates_acceptance_of(:approved)
|
|
|
|
topic = klass.new(approved: true)
|
|
|
|
klass.undefine_attribute_methods
|
2018-12-17 21:18:18 -05:00
|
|
|
assert topic.approved
|
2004-12-19 06:25:55 -05:00
|
|
|
end
|
2009-03-20 17:40:37 -04:00
|
|
|
|
2009-03-20 18:21:27 -04:00
|
|
|
def test_validates_acceptance_of_as_database_column
|
2019-04-13 09:17:54 -04:00
|
|
|
klass = Class.new(Topic)
|
|
|
|
klass.validates_acceptance_of(:approved)
|
|
|
|
topic = klass.create("approved" => true)
|
2010-01-31 22:18:55 -05:00
|
|
|
assert topic["approved"]
|
2009-03-20 18:21:27 -04:00
|
|
|
end
|
2010-01-18 03:56:36 -05:00
|
|
|
|
2010-06-09 23:07:54 -04:00
|
|
|
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
|
|
|
|
|
2014-11-30 20:24:53 -05:00
|
|
|
def test_numericality_validation_with_mutation
|
2016-08-11 07:26:20 -04:00
|
|
|
klass = Class.new(Topic) do
|
2015-02-06 13:05:38 -05:00
|
|
|
attribute :wibble, :string
|
2014-11-30 20:24:53 -05:00
|
|
|
validates_numericality_of :wibble, only_integer: true
|
|
|
|
end
|
|
|
|
|
2016-08-11 07:26:20 -04:00
|
|
|
topic = klass.new(wibble: "123-4567")
|
2016-08-06 12:26:20 -04:00
|
|
|
topic.wibble.gsub!("-", "")
|
2014-11-30 20:24:53 -05:00
|
|
|
|
2018-01-25 18:14:09 -05:00
|
|
|
assert_predicate topic, :valid?
|
2014-11-30 20:24:53 -05:00
|
|
|
end
|
2015-09-25 09:52:37 -04:00
|
|
|
|
2017-05-27 09:47:07 -04:00
|
|
|
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")
|
2017-05-27 09:47:07 -04:00
|
|
|
end
|
|
|
|
|
2018-01-25 18:14:09 -05:00
|
|
|
assert_not_predicate klass.new(wibble: "97.179"), :valid?
|
|
|
|
assert_not_predicate klass.new(wibble: 97.179), :valid?
|
|
|
|
assert_not_predicate klass.new(wibble: BigDecimal("97.179")), :valid?
|
2017-05-27 09:47:07 -04:00
|
|
|
end
|
|
|
|
|
2018-08-10 06:42:00 -04:00
|
|
|
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
|
|
|
|
|
2015-09-25 09:52:37 -04:00
|
|
|
def test_acceptance_validator_doesnt_require_db_connection
|
|
|
|
klass = Class.new(ActiveRecord::Base) do
|
2016-08-06 12:26:20 -04:00
|
|
|
self.table_name = "posts"
|
2015-09-25 09:52:37 -04:00
|
|
|
end
|
|
|
|
klass.reset_column_information
|
|
|
|
|
|
|
|
assert_no_queries do
|
|
|
|
klass.validates_acceptance_of(:foo)
|
|
|
|
end
|
|
|
|
end
|
2005-09-28 22:35:41 -04:00
|
|
|
end
|