mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Disallow all non-numerics as Duration.build input, Fixes #37012
Prevent `ActiveSupport::Duration.build(value)` from creating instances of `ActiveSupport::Duration` unless `value` is of type `Numeric`. Addresses the errant set of behaviours described in #37012 where `ActiveSupport::Duration` comparisons would fail confusingly or return unexpected results when comparing durations built from instances of `String`. Before: small_duration_from_string = ActiveSupport::Duration.build('9') large_duration_from_string = ActiveSupport::Duration.build('100000000000000') small_duration_from_int = ActiveSupport::Duration.build(9) large_duration_from_string > small_duration_from_string => false small_duration_from_string == small_duration_from_int => false small_duration_from_int < large_duration_from_string => ArgumentError (comparison of ActiveSupport::Duration::Scalar with ActiveSupport::Duration failed) large_duration_from_string > small_duration_from_int => ArgumentError (comparison of String with ActiveSupport::Duration failed) After: small_duration_from_string = ActiveSupport::Duration.build('9') => TypeError (can't build an `ActiveSupport::Duration` from a `String`)
This commit is contained in:
parent
1f325fab01
commit
1a48d50363
3 changed files with 53 additions and 0 deletions
|
@ -1,3 +1,36 @@
|
|||
* Prevent `ActiveSupport::Duration.build(value)` from creating instances of
|
||||
`ActiveSupport::Duration` unless `value` is of type `Numeric`.
|
||||
|
||||
Addresses the errant set of behaviours described in #37012 where
|
||||
`ActiveSupport::Duration` comparisons would fail confusingly
|
||||
or return unexpected results when comparing durations built from instances of `String`.
|
||||
|
||||
Before:
|
||||
|
||||
small_duration_from_string = ActiveSupport::Duration.build('9')
|
||||
large_duration_from_string = ActiveSupport::Duration.build('100000000000000')
|
||||
small_duration_from_int = ActiveSupport::Duration.build(9)
|
||||
|
||||
large_duration_from_string > small_duration_from_string
|
||||
=> false
|
||||
|
||||
small_duration_from_string == small_duration_from_int
|
||||
=> false
|
||||
|
||||
small_duration_from_int < large_duration_from_string
|
||||
=> ArgumentError (comparison of ActiveSupport::Duration::Scalar
|
||||
with ActiveSupport::Duration failed)
|
||||
|
||||
large_duration_from_string > small_duration_from_int
|
||||
=> ArgumentError (comparison of String with ActiveSupport::Duration failed)
|
||||
|
||||
After:
|
||||
|
||||
small_duration_from_string = ActiveSupport::Duration.build('9')
|
||||
=> TypeError (can't build an ActiveSupport::Duration from a String)
|
||||
|
||||
*Alexei Emam*
|
||||
|
||||
* Add `ActiveSupport::Cache::Store#delete_multi` method to delete multiple keys from the cache store.
|
||||
|
||||
*Peter Zhu*
|
||||
|
|
|
@ -181,6 +181,10 @@ module ActiveSupport
|
|||
# ActiveSupport::Duration.build(2716146).parts # => {:months=>1, :days=>1}
|
||||
#
|
||||
def build(value)
|
||||
unless value.is_a?(::Numeric)
|
||||
raise TypeError, "can't build an #{self.name} from a #{value.class.name}"
|
||||
end
|
||||
|
||||
parts = {}
|
||||
remainder = value.to_f
|
||||
|
||||
|
|
|
@ -661,6 +661,22 @@ class DurationTest < ActiveSupport::TestCase
|
|||
assert_equal 660, (d1 + 60).to_i
|
||||
end
|
||||
|
||||
def test_string_build_raises_error
|
||||
error = assert_raises(TypeError) do
|
||||
ActiveSupport::Duration.build("9")
|
||||
end
|
||||
|
||||
assert_equal "can't build an ActiveSupport::Duration from a String", error.message
|
||||
end
|
||||
|
||||
def test_non_numeric_build_raises_error
|
||||
error = assert_raises(TypeError) do
|
||||
ActiveSupport::Duration.build(nil)
|
||||
end
|
||||
|
||||
assert_equal "can't build an ActiveSupport::Duration from a NilClass", error.message
|
||||
end
|
||||
|
||||
private
|
||||
def eastern_time_zone
|
||||
if Gem.win_platform?
|
||||
|
|
Loading…
Reference in a new issue