Skip to content

Commit

Permalink
Improve Duration.build String input support
Browse files Browse the repository at this point in the history
Addresses rails/rails github issue rails#37012 by ensuring the value in the objects instantiated by .build is always an integer or float
  • Loading branch information
alexeiemam committed Aug 22, 2019
1 parent 1d7e7db commit 8b86a6f
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
11 changes: 10 additions & 1 deletion activesupport/lib/active_support/duration.rb
Expand Up @@ -182,6 +182,7 @@ def years(value) #:nodoc:
#
def build(value)
parts = {}

remainder = value.to_f

PARTS.each do |part|
Expand All @@ -194,7 +195,15 @@ def build(value)

parts[:seconds] = remainder

new(value, parts)
value_to_instantiate =
case value.class
when Integer
value
else
value_as_processed = value.to_f
(value_as_processed % 1 == 0) ? value_as_processed.to_i : value_as_processed
end
new(value_to_instantiate, parts)
end

private
Expand Down
32 changes: 32 additions & 0 deletions activesupport/test/core_ext/duration_test.rb
Expand Up @@ -661,6 +661,26 @@ def test_durations_survive_yaml_serialization
assert_equal 660, (d1 + 60).to_i
end

def test_less_than_comparator_following_build
a_duration_from_string, a_duration_from_integer = durations_for_build_test
string_duration_smaller_than_integer_duration =
begin
a_duration_from_string < a_duration_from_integer
rescue ArgumentError => _e
"error raised"
end

assert_not string_duration_smaller_than_integer_duration == "error raised"
assert string_duration_smaller_than_integer_duration == false
end

def test_equality_following_build
a_duration_from_string, a_duration_from_integer = durations_for_build_test
string_duration_equals_integer_duration = a_duration_from_string == a_duration_from_integer

assert string_duration_equals_integer_duration == true
end

private
def eastern_time_zone
if Gem.win_platform?
Expand All @@ -669,4 +689,16 @@ def eastern_time_zone
"America/New_York"
end
end

def durations_for_build_test
the_duration_seconds = 23
[
build(the_duration_seconds.to_s),
build(the_duration_seconds)
]
end

def build(it)
ActiveSupport::Duration.build(it)
end
end

0 comments on commit 8b86a6f

Please sign in to comment.