diff options
author | Andrew White <andrew.white@unboxed.co> | 2017-02-27 18:31:35 +0000 |
---|---|---|
committer | Andrew White <andrew.white@unboxed.co> | 2017-03-02 08:00:22 +0000 |
commit | 75924c4517c8f87712d3f59c11f10152ed57b9d8 (patch) | |
tree | 5ea1e0dd022c66f96662b5745df591ae5714c6f7 /activesupport/test/core_ext/duration_test.rb | |
parent | a815c7c7214d0c45194bc9b097e20f50a2b0aab1 (diff) | |
download | rails-75924c4517c8f87712d3f59c11f10152ed57b9d8.tar.gz rails-75924c4517c8f87712d3f59c11f10152ed57b9d8.tar.bz2 rails-75924c4517c8f87712d3f59c11f10152ed57b9d8.zip |
Deprecate implicit coercion of `ActiveSupport::Duration`
Currently `ActiveSupport::Duration` implicitly converts to a seconds
value when used in a calculation except for the explicit examples of
addition and subtraction where the duration is the receiver, e.g:
>> 2 * 1.day
=> 172800
This results in lots of confusion especially when using durations
with dates because adding/subtracting a value from a date treats
integers as a day and not a second, e.g:
>> Date.today
=> Wed, 01 Mar 2017
>> Date.today + 2 * 1.day
=> Mon, 10 Apr 2490
To fix this we're implementing `coerce` so that we can provide a
deprecation warning with the intent of removing the implicit coercion
in Rails 5.2, e.g:
>> 2 * 1.day
DEPRECATION WARNING: Implicit coercion of ActiveSupport::Duration
to a Numeric is deprecated and will raise a TypeError in Rails 5.2.
=> 172800
In Rails 5.2 it will raise `TypeError`, e.g:
>> 2 * 1.day
TypeError: ActiveSupport::Duration can't be coerced into Integer
This is the same behavior as with other types in Ruby, e.g:
>> 2 * "foo"
TypeError: String can't be coerced into Integer
>> "foo" * 2
=> "foofoo"
As part of this deprecation add `*` and `/` methods to `AS::Duration`
so that calculations that keep the duration as the receiver work
correctly whether the final receiver is a `Date` or `Time`, e.g:
>> Date.today
=> Wed, 01 Mar 2017
>> Date.today + 1.day * 2
=> Fri, 03 Mar 2017
Fixes #27457.
Diffstat (limited to 'activesupport/test/core_ext/duration_test.rb')
-rw-r--r-- | activesupport/test/core_ext/duration_test.rb | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index 6facb04f1f..2b1a715b7a 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -84,8 +84,46 @@ class DurationTest < ActiveSupport::TestCase assert_nothing_raised { Date.today - Date.today } end + def test_plus + assert_equal 2.seconds, 1.second + 1.second + assert_instance_of ActiveSupport::Duration, 1.second + 1.second + assert_equal 2.seconds, 1.second + 1 + assert_instance_of ActiveSupport::Duration, 1.second + 1 + end + + def test_minus + assert_equal 1.second, 2.seconds - 1.second + assert_instance_of ActiveSupport::Duration, 2.seconds - 1.second + assert_equal 1.second, 2.seconds - 1 + assert_instance_of ActiveSupport::Duration, 2.seconds - 1 + end + + def test_multiply + assert_equal 7.days, 1.day * 7 + assert_instance_of ActiveSupport::Duration, 1.day * 7 + + assert_deprecated do + assert_equal 86400, 1.day * 1.second + end + end + + def test_divide + assert_equal 1.day, 7.days / 7 + assert_instance_of ActiveSupport::Duration, 7.days / 7 + + assert_deprecated do + assert_equal 1, 1.day / 1.day + end + end + + def test_date_added_with_multiplied_duration + assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 1.day * 2 + end + def test_plus_with_time - assert_equal 1 + 1.second, 1.second + 1, "Duration + Numeric should == Numeric + Duration" + assert_deprecated do + assert_equal 1 + 1.second, 1.second + 1, "Duration + Numeric should == Numeric + Duration" + end end def test_time_plus_duration_returns_same_time_datatype @@ -104,6 +142,13 @@ class DurationTest < ActiveSupport::TestCase assert_equal 'expected a time or date, got ""', e.message, "ensure ArgumentError is not being raised by dependencies.rb" end + def test_implicit_coercion_is_deprecated + assert_deprecated { 1 + 1.second } + assert_deprecated { 1 - 1.second } + assert_deprecated { 1 * 1.second } + assert_deprecated { 1 / 1.second } + end + def test_fractional_weeks assert_equal((86400 * 7) * 1.5, 1.5.weeks) assert_equal((86400 * 7) * 1.7, 1.7.weeks) @@ -241,13 +286,20 @@ class DurationTest < ActiveSupport::TestCase def test_comparable assert_equal(-1, (0.seconds <=> 1.second)) assert_equal(-1, (1.second <=> 1.minute)) - assert_equal(-1, (1 <=> 1.minute)) + + assert_deprecated do + assert_equal(-1, (1 <=> 1.minute)) + end + assert_equal(0, (0.seconds <=> 0.seconds)) assert_equal(0, (0.seconds <=> 0.minutes)) assert_equal(0, (1.second <=> 1.second)) assert_equal(1, (1.second <=> 0.second)) assert_equal(1, (1.minute <=> 1.second)) - assert_equal(1, (61 <=> 1.minute)) + + assert_deprecated do + assert_equal(1, (61 <=> 1.minute)) + end end def test_twelve_months_equals_one_year |