Merge branch 'deprecate_numeric_since_ago' of https://github.com/chancancode/rails

Conflicts:
	activesupport/CHANGELOG.md
This commit is contained in:
Jeremy Kemper 2013-11-27 03:47:35 -07:00
commit d4016f24fb
4 changed files with 58 additions and 31 deletions

View File

@ -1,3 +1,20 @@
* Deprecated Numeric#{ago,until,since,from_now}, the user is expected to explicitly
convert the value into an AS::Duration, i.e. 5.ago => 5.seconds.ago
This will help to catch subtle bugs like:
def recent?(days = 3)
self.created_at >= days.ago
end
The above code would check if the model is created within the last 3 **seconds**.
In the future, Numeric#{ago,until,since,from_now} should be removed completely,
or throw some sort of errors to indicate there are no implicit conversion from
Numeric to AS::Duration.
*Godfrey Chan*
* Requires JSON gem version 1.7.7 or above due to a security issue in older versions. * Requires JSON gem version 1.7.7 or above due to a security issue in older versions.
*Godfrey Chan* *Godfrey Chan*

View File

@ -63,6 +63,7 @@ class Numeric
# Reads best without arguments: 10.minutes.ago # Reads best without arguments: 10.minutes.ago
def ago(time = ::Time.current) def ago(time = ::Time.current)
ActiveSupport::Deprecation.warn "Calling #ago or #until on a number (e.g. 5.ago) is deprecated and will be removed in the future, use 5.seconds.ago instead"
time - self time - self
end end
@ -71,6 +72,7 @@ class Numeric
# Reads best with argument: 10.minutes.since(time) # Reads best with argument: 10.minutes.since(time)
def since(time = ::Time.current) def since(time = ::Time.current)
ActiveSupport::Deprecation.warn "Calling #since or #from_now on a number (e.g. 5.since) is deprecated and will be removed in the future, use 5.seconds.since instead"
time + self time + self
end end

View File

@ -71,6 +71,19 @@ class DurationTest < ActiveSupport::TestCase
assert_equal 86400 * 1.7, 1.7.days assert_equal 86400 * 1.7, 1.7.days
end end
def test_since_and_ago
t = Time.local(2000)
assert t + 1, 1.second.since(t)
assert t - 1, 1.second.ago(t)
end
def test_since_and_ago_without_argument
now = Time.now
assert 1.second.since >= now + 1
now = Time.now
assert 1.second.ago >= now - 1
end
def test_since_and_ago_with_fractional_days def test_since_and_ago_with_fractional_days
t = Time.local(2000) t = Time.local(2000)
# since # since
@ -96,10 +109,10 @@ class DurationTest < ActiveSupport::TestCase
with_env_tz 'US/Eastern' do with_env_tz 'US/Eastern' do
Time.stubs(:now).returns Time.local(2000) Time.stubs(:now).returns Time.local(2000)
# since # since
assert_equal false, 5.seconds.since.is_a?(ActiveSupport::TimeWithZone) assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.since
assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since
# ago # ago
assert_equal false, 5.seconds.ago.is_a?(ActiveSupport::TimeWithZone) assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago
assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago
end end
end end
@ -109,11 +122,11 @@ class DurationTest < ActiveSupport::TestCase
with_env_tz 'US/Eastern' do with_env_tz 'US/Eastern' do
Time.stubs(:now).returns Time.local(2000) Time.stubs(:now).returns Time.local(2000)
# since # since
assert_equal true, 5.seconds.since.is_a?(ActiveSupport::TimeWithZone) assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.since
assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time
assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name
# ago # ago
assert_equal true, 5.seconds.ago.is_a?(ActiveSupport::TimeWithZone) assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago
assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time
assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name
end end

View File

@ -22,21 +22,16 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase
end end
end end
def test_intervals def test_deprecated_since_and_ago
@seconds.values.each do |seconds| assert_equal @now + 1, assert_deprecated { 1.since(@now) }
assert_equal seconds.since(@now), @now + seconds assert_equal @now - 1, assert_deprecated { 1.ago(@now) }
assert_equal seconds.until(@now), @now - seconds
end
end end
# Test intervals based from Time.now def test_deprecated_since_and_ago_without_argument
def test_now now = Time.now
@seconds.values.each do |seconds| assert assert_deprecated { 1.since } >= now + 1
now = Time.now now = Time.now
assert seconds.ago >= now - seconds assert assert_deprecated { 1.ago } >= now - 1
now = Time.now
assert seconds.from_now >= now + seconds
end
end end
def test_irregular_durations def test_irregular_durations
@ -78,10 +73,10 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase
end end
def test_duration_after_conversion_is_no_longer_accurate def test_duration_after_conversion_is_no_longer_accurate
assert_equal 30.days.to_i.since(@now), 1.month.to_i.since(@now) assert_equal 30.days.to_i.seconds.since(@now), 1.month.to_i.seconds.since(@now)
assert_equal 365.25.days.to_f.since(@now), 1.year.to_f.since(@now) assert_equal 365.25.days.to_f.seconds.since(@now), 1.year.to_f.seconds.since(@now)
assert_equal 30.days.to_i.since(@dtnow), 1.month.to_i.since(@dtnow) assert_equal 30.days.to_i.seconds.since(@dtnow), 1.month.to_i.seconds.since(@dtnow)
assert_equal 365.25.days.to_f.since(@dtnow), 1.year.to_f.since(@dtnow) assert_equal 365.25.days.to_f.seconds.since(@dtnow), 1.year.to_f.seconds.since(@dtnow)
end end
def test_add_one_year_to_leap_day def test_add_one_year_to_leap_day
@ -94,11 +89,11 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase
with_env_tz 'US/Eastern' do with_env_tz 'US/Eastern' do
Time.stubs(:now).returns Time.local(2000) Time.stubs(:now).returns Time.local(2000)
# since # since
assert_equal false, 5.since.is_a?(ActiveSupport::TimeWithZone) assert_not_instance_of ActiveSupport::TimeWithZone, assert_deprecated { 5.since }
assert_equal Time.local(2000,1,1,0,0,5), 5.since assert_equal Time.local(2000,1,1,0,0,5), assert_deprecated { 5.since }
# ago # ago
assert_equal false, 5.ago.is_a?(ActiveSupport::TimeWithZone) assert_not_instance_of ActiveSupport::TimeWithZone, assert_deprecated { 5.ago }
assert_equal Time.local(1999,12,31,23,59,55), 5.ago assert_equal Time.local(1999,12,31,23,59,55), assert_deprecated { 5.ago }
end end
end end
@ -107,13 +102,13 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase
with_env_tz 'US/Eastern' do with_env_tz 'US/Eastern' do
Time.stubs(:now).returns Time.local(2000) Time.stubs(:now).returns Time.local(2000)
# since # since
assert_equal true, 5.since.is_a?(ActiveSupport::TimeWithZone) assert_instance_of ActiveSupport::TimeWithZone, assert_deprecated { 5.since }
assert_equal Time.utc(2000,1,1,0,0,5), 5.since.time assert_equal Time.utc(2000,1,1,0,0,5), assert_deprecated { 5.since.time }
assert_equal 'Eastern Time (US & Canada)', 5.since.time_zone.name assert_equal 'Eastern Time (US & Canada)', assert_deprecated { 5.since.time_zone.name }
# ago # ago
assert_equal true, 5.ago.is_a?(ActiveSupport::TimeWithZone) assert_instance_of ActiveSupport::TimeWithZone, assert_deprecated { 5.ago }
assert_equal Time.utc(1999,12,31,23,59,55), 5.ago.time assert_equal Time.utc(1999,12,31,23,59,55), assert_deprecated { 5.ago.time }
assert_equal 'Eastern Time (US & Canada)', 5.ago.time_zone.name assert_equal 'Eastern Time (US & Canada)', assert_deprecated { 5.ago.time_zone.name }
end end
ensure ensure
Time.zone = nil Time.zone = nil