aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorAndrew White <andrew.white@unboxed.co>2017-07-27 12:30:17 +0100
committerAndrew White <andrew.white@unboxed.co>2017-07-27 13:41:44 +0100
commitbfa878d3b2a814db4d781143c9f5248b642900d0 (patch)
tree9b70ede48f605926028933ed7c58fbe44503df4c /activesupport
parentd3c1266c338c3a37181c0a131c7d983e5e30c8d0 (diff)
downloadrails-bfa878d3b2a814db4d781143c9f5248b642900d0.tar.gz
rails-bfa878d3b2a814db4d781143c9f5248b642900d0.tar.bz2
rails-bfa878d3b2a814db4d781143c9f5248b642900d0.zip
Fix division where a duration is the denominator
PR #29163 introduced a change in behavior when a duration was the denominator in a calculation - this was incorrect as dividing by a duration should always return a `Numeric`. The behavior of previous versions of Rails has been restored. Fixes #29592.
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG.md10
-rw-r--r--activesupport/lib/active_support/duration.rb9
-rw-r--r--activesupport/test/core_ext/duration_test.rb24
3 files changed, 28 insertions, 15 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 457eb84a62..42d3467e7d 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,13 @@
+* Fix division where a duration is the denominator
+
+ PR #29163 introduced a change in behavior when a duration was the denominator
+ in a calculation - this was incorrect as dividing by a duration should always
+ return a `Numeric`. The behavior of previous versions of Rails has been restored.
+
+ Fixes #29592.
+
+ *Andrew White*
+
* Add purpose and expiry support to `ActiveSupport::MessageVerifier` &
`ActiveSupport::MessageEncryptor`.
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index 068adcea24..0d45566d43 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -76,10 +76,7 @@ module ActiveSupport
def /(other)
if Duration === other
- new_parts = other.parts.map { |part, other_value| [part, value / other_value] }.to_h
- new_value = new_parts.inject(0) { |total, (part, value)| total + value * Duration::PARTS_IN_SECONDS[part] }
-
- Duration.new(new_value, new_parts)
+ value / other.value
else
calculate(:/, other)
end
@@ -234,8 +231,10 @@ module ActiveSupport
# Divides this Duration by a Numeric and returns a new Duration.
def /(other)
- if Scalar === other || Duration === other
+ if Scalar === other
Duration.new(value / other.value, parts.map { |type, number| [type, number / other.value] })
+ elsif Duration === other
+ value / other.value
elsif Numeric === other
Duration.new(value / other, parts.map { |type, number| [type, number / other] })
else
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index c655f466f2..1d607a20a6 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -410,9 +410,11 @@ class DurationTest < ActiveSupport::TestCase
assert_equal 5, scalar / 2
assert_instance_of ActiveSupport::Duration::Scalar, scalar / 2
assert_equal 10, 100.seconds / scalar
+ assert_instance_of ActiveSupport::Duration, 100.seconds / scalar
+ assert_equal 20, 2.seconds * scalar
assert_instance_of ActiveSupport::Duration, 2.seconds * scalar
assert_equal 5, scalar / 2.seconds
- assert_instance_of ActiveSupport::Duration, scalar / 2.seconds
+ assert_kind_of Integer, scalar / 2.seconds
exception = assert_raises(TypeError) do
scalar / "foo"
@@ -421,15 +423,6 @@ class DurationTest < ActiveSupport::TestCase
assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
end
- def test_scalar_divide_parts
- scalar = ActiveSupport::Duration::Scalar.new(10)
-
- assert_equal({ days: 2 }, (scalar / 5.days).parts)
- assert_equal(172800, (scalar / 5.days).value)
- assert_equal({ days: -2 }, (scalar / -5.days).parts)
- assert_equal(-172800, (scalar / -5.days).value)
- end
-
def test_twelve_months_equals_one_year
assert_equal 12.months, 1.year
end
@@ -438,6 +431,17 @@ class DurationTest < ActiveSupport::TestCase
assert_not_equal 30.days, 1.month
end
+ def test_division
+ assert_equal 1.hour, 1.day / 24
+ assert_instance_of ActiveSupport::Duration, 1.day / 24
+
+ assert_equal 24, 86400 / 1.hour
+ assert_kind_of Integer, 86400 / 1.hour
+
+ assert_equal 24, 1.day / 1.hour
+ assert_kind_of Integer, 1.day / 1.hour
+ end
+
def test_adding_one_month_maintains_day_of_month
(1..11).each do |month|
[1, 14, 28].each do |day|