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:
parent
a0b57bbb21
commit
47a6d788dd
4 changed files with 41 additions and 4 deletions
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue