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

Fix numericality validator to still use value before type cast except Active Record

The purpose of fe9547b is to work type casting to value from database.

But that was caused not to use the value before type cast even except
Active Record.

There we never guarantees that the value before type cast was going to
the used in this validation, but we should not change the behavior
unless there is some particular reason.

To restore original behavior, still use the value before type cast if
`came_from_user?` is undefined (i.e. except Active Record).

Fixes #33651.
Fixes #33686.
This commit is contained in:
Ryuta Kamizono 2018-08-19 14:57:05 +09:00
parent a0b57bbb21
commit 47a6d788dd
4 changed files with 41 additions and 4 deletions

View file

@ -1,3 +1,9 @@
* Fix numericality validator to still use value before type cast except Active Record.
Fixes #33651, #33686.
*Ryuta Kamizono*
* Fix `ActiveModel::Serializers::JSON#as_json` method for timestamps.
Before:

View file

@ -21,10 +21,17 @@ module ActiveModel
def validate_each(record, attr_name, value)
came_from_user = :"#{attr_name}_came_from_user?"
if record.respond_to?(came_from_user) && record.public_send(came_from_user)
raw_value = record.read_attribute_before_type_cast(attr_name)
elsif record.respond_to?(:read_attribute)
raw_value = record.read_attribute(attr_name)
if record.respond_to?(came_from_user)
if record.public_send(came_from_user)
raw_value = record.read_attribute_before_type_cast(attr_name)
elsif record.respond_to?(:read_attribute)
raw_value = record.read_attribute(attr_name)
end
else
before_type_cast = :"#{attr_name}_before_type_cast"
if record.respond_to?(before_type_cast)
raw_value = record.public_send(before_type_cast)
end
end
raw_value ||= value

View file

@ -262,6 +262,16 @@ class NumericalityValidationTest < ActiveModel::TestCase
Person.clear_validators!
end
def test_validates_numericality_using_value_before_type_cast_if_possible
Topic.validates_numericality_of :price
topic = Topic.new(price: 50)
assert_equal "$50.00", topic.price
assert_equal 50, topic.price_before_type_cast
assert_predicate topic, :valid?
end
def test_validates_numericality_with_exponent_number
base = 10_000_000_000_000_000
Topic.validates_numericality_of :approved, less_than_or_equal_to: base

View file

@ -3,6 +3,11 @@
class Topic
include ActiveModel::Validations
include ActiveModel::Validations::Callbacks
include ActiveModel::AttributeMethods
include ActiveSupport::NumberHelper
attribute_method_suffix "_before_type_cast"
define_attribute_method :price
def self._validates_default_keys
super | [ :message ]
@ -10,6 +15,7 @@ class Topic
attr_accessor :title, :author_name, :content, :approved, :created_at
attr_accessor :after_validation_performed
attr_writer :price
after_validation :perform_after_validation
@ -38,4 +44,12 @@ class Topic
def my_validation_with_arg(attr)
errors.add attr, "is missing" unless send(attr)
end
def price
number_to_currency @price
end
def attribute_before_type_cast(attr)
instance_variable_get(:"@#{attr}")
end
end