Always assume strings with non-numeric characters change numeric types
We previously only did this if the old value was zero, to make sure numericality validations run and failed if the user gave 'wibble' as the value, which would be type cast to 0. However, numericality validations will fail if there are any non-numeric characters in the string, so 5 -> '5wibble' should also be marked as changed.
This commit is contained in:
parent
9ac1ce11ad
commit
50fa366783
@ -1,3 +1,17 @@
|
||||
* Assume numeric types have changed if they were assigned to a value that
|
||||
would fail numericality validation, regardless of the old value. Previously
|
||||
this would only occur if the old value was 0.
|
||||
|
||||
Example:
|
||||
|
||||
model = Model.create!(number: 5)
|
||||
model.number = '5wibble'
|
||||
model.number_changed? # => true
|
||||
|
||||
Fixes #14731.
|
||||
|
||||
*Sean Griffin*
|
||||
|
||||
* `reload` no longer merges with the existing attributes.
|
||||
The attribute hash is fully replaced. The record is put into the same state
|
||||
as it would be with `Model.find(model.id)`.
|
||||
|
@ -16,13 +16,13 @@ def type_cast(value)
|
||||
end
|
||||
|
||||
def changed?(old_value, _new_value, new_value_before_type_cast) # :nodoc:
|
||||
super || zero_to_non_number?(old_value, new_value_before_type_cast)
|
||||
super || number_to_non_number?(old_value, new_value_before_type_cast)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def zero_to_non_number?(old_value, new_value_before_type_cast)
|
||||
old_value == 0 && non_numeric_string?(new_value_before_type_cast)
|
||||
def number_to_non_number?(old_value, new_value_before_type_cast)
|
||||
old_value != nil && non_numeric_string?(new_value_before_type_cast)
|
||||
end
|
||||
|
||||
def non_numeric_string?(value)
|
||||
|
@ -79,11 +79,29 @@ def test_type_cast_nan_and_infinity_to_integer
|
||||
assert_nil type.type_cast_from_user(1.0/0.0)
|
||||
end
|
||||
|
||||
def test_changing_integers
|
||||
type = Type::Integer.new
|
||||
|
||||
assert type.changed?(5, 5, '5wibble')
|
||||
assert_not type.changed?(5, 5, '5')
|
||||
assert_not type.changed?(5, 5, '5.0')
|
||||
assert_not type.changed?(nil, nil, nil)
|
||||
end
|
||||
|
||||
def test_type_cast_float
|
||||
type = Type::Float.new
|
||||
assert_equal 1.0, type.type_cast_from_user("1")
|
||||
end
|
||||
|
||||
def test_changing_float
|
||||
type = Type::Float.new
|
||||
|
||||
assert type.changed?(5.0, 5.0, '5wibble')
|
||||
assert_not type.changed?(5.0, 5.0, '5')
|
||||
assert_not type.changed?(5.0, 5.0, '5.0')
|
||||
assert_not type.changed?(nil, nil, nil)
|
||||
end
|
||||
|
||||
def test_type_cast_decimal
|
||||
type = Type::Decimal.new
|
||||
assert_equal BigDecimal.new("0"), type.type_cast_from_user(BigDecimal.new("0"))
|
||||
|
Loading…
Reference in New Issue
Block a user