aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG.md28
-rw-r--r--activemodel/lib/active_model/type/time.rb2
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb13
-rw-r--r--activemodel/test/cases/type/time_test.rb1
-rw-r--r--activemodel/test/cases/validations/numericality_validation_test.rb13
5 files changed, 48 insertions, 9 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 571c050f2f..912b307683 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,31 @@
+* Fix year value when casting a multiparameter time hash
+
+ When assigning a hash to a time attribute that's missing a year component
+ (e.g. a `time_select` with `:ignore_date` set to `true`) then the year
+ defaults to 1970 instead of the expected 2000. This results in the attribute
+ changing as a result of the save.
+
+ Before:
+ ```
+ event = Event.new(start_time: { 4 => 20, 5 => 30 })
+ event.start_time # => 1970-01-01 20:30:00 UTC
+ event.save
+ event.reload
+ event.start_time # => 2000-01-01 20:30:00 UTC
+ ```
+
+ After:
+ ```
+ event = Event.new(start_time: { 4 => 20, 5 => 30 })
+ event.start_time # => 2000-01-01 20:30:00 UTC
+ event.save
+ event.reload
+ event.start_time # => 2000-01-01 20:30:00 UTC
+ ```
+
+ *Andrew White*
+
+
## Rails 6.0.0.beta1 (January 18, 2019) ##
* Add `ActiveModel::Errors#of_kind?`.
diff --git a/activemodel/lib/active_model/type/time.rb b/activemodel/lib/active_model/type/time.rb
index b3056b1333..8fba01b86a 100644
--- a/activemodel/lib/active_model/type/time.rb
+++ b/activemodel/lib/active_model/type/time.rb
@@ -5,7 +5,7 @@ module ActiveModel
class Time < Value # :nodoc:
include Helpers::TimeValue
include Helpers::AcceptsMultiparameterTime.new(
- defaults: { 1 => 1970, 2 => 1, 3 => 1, 4 => 0, 5 => 0 }
+ defaults: { 1 => 2000, 2 => 1, 3 => 1, 4 => 0, 5 => 0 }
)
def type
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index c5997283ea..51e224d5cd 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require "bigdecimal/util"
+
module ActiveModel
module Validations
class NumericalityValidator < EachValidator # :nodoc:
@@ -10,7 +12,6 @@ module ActiveModel
RESERVED_OPTIONS = CHECKS.keys + [:only_integer]
INTEGER_REGEX = /\A[+-]?\d+\z/
- DECIMAL_REGEX = /\A[+-]?\d+\.?\d*(e|e[+-])?\d+\z/
def check_validity!
keys = CHECKS.keys - [:odd, :even]
@@ -92,8 +93,8 @@ module ActiveModel
raw_value
elsif is_integer?(raw_value)
raw_value.to_i
- elsif is_decimal?(raw_value) && !is_hexadecimal_literal?(raw_value)
- BigDecimal(raw_value)
+ elsif !is_hexadecimal_literal?(raw_value)
+ Kernel.Float(raw_value).to_d
end
end
@@ -101,12 +102,8 @@ module ActiveModel
INTEGER_REGEX.match?(raw_value.to_s)
end
- def is_decimal?(raw_value)
- DECIMAL_REGEX.match?(raw_value.to_s)
- end
-
def is_hexadecimal_literal?(raw_value)
- /\A0[xX]/.match?(raw_value)
+ /\A0[xX]/.match?(raw_value.to_s)
end
def filtered_options(value)
diff --git a/activemodel/test/cases/type/time_test.rb b/activemodel/test/cases/type/time_test.rb
index 3fbae1a169..5c6271241d 100644
--- a/activemodel/test/cases/type/time_test.rb
+++ b/activemodel/test/cases/type/time_test.rb
@@ -16,6 +16,7 @@ module ActiveModel
assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast("2015-06-13T19:45:54+03:00")
assert_equal ::Time.utc(1999, 12, 31, 21, 7, 8), type.cast("06:07:08+09:00")
+ assert_equal ::Time.utc(2000, 1, 1, 16, 45, 54), type.cast(4 => 16, 5 => 45, 6 => 54)
end
def test_user_input_in_time_zone
diff --git a/activemodel/test/cases/validations/numericality_validation_test.rb b/activemodel/test/cases/validations/numericality_validation_test.rb
index eb4b02df93..fcdf123062 100644
--- a/activemodel/test/cases/validations/numericality_validation_test.rb
+++ b/activemodel/test/cases/validations/numericality_validation_test.rb
@@ -281,6 +281,19 @@ class NumericalityValidationTest < ActiveModel::TestCase
assert_predicate topic, :invalid?
end
+ def test_validates_numericalty_with_object_acting_as_numeric
+ klass = Class.new do
+ def to_f
+ 123.54
+ end
+ end
+
+ Topic.validates_numericality_of :price
+ topic = Topic.new(price: klass.new)
+
+ assert_predicate topic, :valid?
+ end
+
def test_validates_numericality_with_invalid_args
assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, greater_than_or_equal_to: "foo" }
assert_raise(ArgumentError) { Topic.validates_numericality_of :approved, less_than_or_equal_to: "foo" }