diff options
Diffstat (limited to 'activesupport')
27 files changed, 466 insertions, 95 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 450669968b..7b93731917 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,22 @@ ## Rails 4.0.0 (unreleased) ## +* Deprecate `Time.time_with_date_fallback`, `Time.utc_time` and `Time.local_time`. + These methods were added to handle the limited range of Ruby's native Time + implementation. Those limitations no longer apply so we are deprecating them in 4.0 + and they will be removed in 4.1. + + *Andrew White* + +* Deprecate `Date#to_time_in_current_zone` and add `Date#in_time_zone`. *Andrew White* + +* Add `String#in_time_zone` method to convert a string to an ActiveSupport::TimeWithZone. *Andrew White* + +* Deprecate `ActiveSupport::BasicObject` in favor of `ActiveSupport::ProxyObject`. + This class is used for proxy classes. It avoids confusion with Ruby's BasicObject + class. + + *Francesco Rodriguez* + * Patched Marshal#load to work with constant autoloading. Fixes autoloading with cache stores that relay on Marshal(MemCacheStore and FileStore). [fixes #8167] diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index 4e397ea110..b602686114 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -40,6 +40,7 @@ module ActiveSupport eager_autoload do autoload :BacktraceCleaner autoload :BasicObject + autoload :ProxyObject autoload :Benchmarkable autoload :Cache autoload :Callbacks diff --git a/activesupport/lib/active_support/basic_object.rb b/activesupport/lib/active_support/basic_object.rb index 6ccb0cd525..242b766b58 100644 --- a/activesupport/lib/active_support/basic_object.rb +++ b/activesupport/lib/active_support/basic_object.rb @@ -1,13 +1,7 @@ -module ActiveSupport - # A class with no predefined methods that behaves similarly to Builder's - # BlankSlate. Used for proxy classes. - class BasicObject < ::BasicObject - undef_method :== - undef_method :equal? +require 'active_support/deprecation' - # Let ActiveSupport::BasicObject at least raise exceptions. - def raise(*args) - ::Object.send(:raise, *args) - end - end +module ActiveSupport + # :nodoc: + # Deprecated in favor of ActiveSupport::ProxyObject + BasicObject = Deprecation::DeprecatedConstantProxy.new('ActiveSupport::BasicObject', 'ActiveSupport::ProxyObject') end diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index 1c3d26ead4..1504e18839 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -72,6 +72,9 @@ class Class instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true) instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true) + # We use class_eval here rather than define_method because class_attribute + # may be used in a performance sensitive context therefore the overhead that + # define_method introduces may become significant. attrs.each do |name| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def self.#{name}() nil end diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 439d380af7..421aa12100 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -53,19 +53,19 @@ class Date # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00) # and then subtracts the specified number of seconds. def ago(seconds) - to_time_in_current_zone.since(-seconds) + in_time_zone.since(-seconds) end # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00) # and then adds the specified number of seconds def since(seconds) - to_time_in_current_zone.since(seconds) + in_time_zone.since(seconds) end alias :in :since # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00) def beginning_of_day - to_time_in_current_zone + in_time_zone end alias :midnight :beginning_of_day alias :at_midnight :beginning_of_day @@ -73,8 +73,9 @@ class Date # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59) def end_of_day - to_time_in_current_zone.end_of_day + in_time_zone.end_of_day end + alias :at_end_of_day :end_of_day def plus_with_duration(other) #:nodoc: if ActiveSupport::Duration === other diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index 9120b0ba49..fe08ade7e0 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -75,10 +75,10 @@ class Date # # date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007 def to_time(form = :local) - ::Time.send("#{form}_time", year, month, day) + ::Time.send(form, year, month, day) end def xmlschema - to_time_in_current_zone.xmlschema + in_time_zone.xmlschema end end diff --git a/activesupport/lib/active_support/core_ext/date/zones.rb b/activesupport/lib/active_support/core_ext/date/zones.rb index c1b3934722..b4548671bf 100644 --- a/activesupport/lib/active_support/core_ext/date/zones.rb +++ b/activesupport/lib/active_support/core_ext/date/zones.rb @@ -2,14 +2,36 @@ require 'date' require 'active_support/core_ext/time/zones' class Date + # *DEPRECATED*: Use +Date#in_time_zone+ instead. + # # Converts Date to a TimeWithZone in the current zone if <tt>Time.zone</tt> or # <tt>Time.zone_default</tt> is set, otherwise converts Date to a Time via # Date#to_time. def to_time_in_current_zone + ActiveSupport::Deprecation.warn 'Date#to_time_in_current_zone is deprecated. Use Date#in_time_zone instead', caller + if ::Time.zone ::Time.zone.local(year, month, day) else to_time end end + + # Converts Date to a TimeWithZone in the current zone if Time.zone or Time.zone_default + # is set, otherwise converts Date to a Time via Date#to_time + # + # Time.zone = 'Hawaii' # => 'Hawaii' + # Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00 + # + # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument, + # and the conversion will be based on that zone instead of <tt>Time.zone</tt>. + # + # Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00 + def in_time_zone(zone = ::Time.zone) + if zone + ::Time.find_zone!(zone).local(year, month, day) + else + to_time + end + end end diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index f77d444479..fca5d4d679 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -110,6 +110,7 @@ class DateTime def end_of_day change(:hour => 23, :min => 59, :sec => 59) end + alias :at_end_of_day :end_of_day # Returns a new DateTime representing the start of the hour (hh:00:00). def beginning_of_hour @@ -121,6 +122,7 @@ class DateTime def end_of_hour change(:min => 59, :sec => 59) end + alias :at_end_of_hour :end_of_hour # Adjusts DateTime to UTC by adding its offset value; offset is set to 0. # diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb index ad864765a3..5d7cb81e38 100644 --- a/activesupport/lib/active_support/core_ext/string.rb +++ b/activesupport/lib/active_support/core_ext/string.rb @@ -11,3 +11,4 @@ require 'active_support/core_ext/string/exclude' require 'active_support/core_ext/string/strip' require 'active_support/core_ext/string/inquiry' require 'active_support/core_ext/string/indent' +require 'active_support/core_ext/string/zones' diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb index 9b9d83932e..9d3b81cf38 100644 --- a/activesupport/lib/active_support/core_ext/string/conversions.rb +++ b/activesupport/lib/active_support/core_ext/string/conversions.rb @@ -21,7 +21,7 @@ class String date_values[6] *= 1000000 offset = date_values.pop - ::Time.send("#{form}_time", *date_values) - offset + ::Time.send(form, *date_values) - offset end end diff --git a/activesupport/lib/active_support/core_ext/string/zones.rb b/activesupport/lib/active_support/core_ext/string/zones.rb new file mode 100644 index 0000000000..e3f20eee29 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/string/zones.rb @@ -0,0 +1,13 @@ +require 'active_support/core_ext/time/zones' + +class String + # Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default + # is set, otherwise converts String to a Time via String#to_time + def in_time_zone(zone = ::Time.zone) + if zone + ::Time.find_zone!(zone).parse(self) + else + to_time + end + end +end diff --git a/activesupport/lib/active_support/core_ext/thread.rb b/activesupport/lib/active_support/core_ext/thread.rb new file mode 100644 index 0000000000..6ad0b2d69c --- /dev/null +++ b/activesupport/lib/active_support/core_ext/thread.rb @@ -0,0 +1,70 @@ +class Thread + LOCK = Mutex.new # :nodoc: + + # Returns the value of a thread local variable that has been set. Note that + # these are different than fiber local values. + # + # Thread local values are carried along with threads, and do not respect + # fibers. For example: + # + # Thread.new { + # Thread.current.thread_variable_set("foo", "bar") # set a thread local + # Thread.current["foo"] = "bar" # set a fiber local + # + # Fiber.new { + # Fiber.yield [ + # Thread.current.thread_variable_get("foo"), # get the thread local + # Thread.current["foo"], # get the fiber local + # ] + # }.resume + # }.join.value # => ['bar', nil] + # + # The value <tt>"bar"</tt> is returned for the thread local, where +nil+ is returned + # for the fiber local. The fiber is executed in the same thread, so the + # thread local values are available. + def thread_variable_get(key) + locals[key.to_sym] + end + + # Sets a thread local with +key+ to +value+. Note that these are local to + # threads, and not to fibers. Please see Thread#thread_variable_get for + # more information. + def thread_variable_set(key, value) + locals[key.to_sym] = value + end + + # Returns an an array of the names of the thread-local variables (as Symbols). + # + # thr = Thread.new do + # Thread.current.thread_variable_set(:cat, 'meow') + # Thread.current.thread_variable_set("dog", 'woof') + # end + # thr.join #=> #<Thread:0x401b3f10 dead> + # thr.thread_variables #=> [:dog, :cat] + # + # Note that these are not fiber local variables. Please see Thread#thread_variable_get + # for more details. + def thread_variables + locals.keys + end + + # Returns <tt>true</tt> if the given string (or symbol) exists as a + # thread-local variable. + # + # me = Thread.current + # me.thread_variable_set(:oliver, "a") + # me.thread_variable?(:oliver) #=> true + # me.thread_variable?(:stanley) #=> false + # + # Note that these are not fiber local variables. Please see Thread#thread_variable_get + # for more details. + def thread_variable?(key) + locals.has_key?(key.to_sym) + end + + private + + def locals + @locals || LOCK.synchronize { @locals ||= {} } + end +end unless Thread.instance_methods.include?(:thread_variable_set) diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 46c9f05c15..1f95f62229 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -3,6 +3,7 @@ require 'active_support/core_ext/time/conversions' require 'active_support/time_with_zone' require 'active_support/core_ext/time/zones' require 'active_support/core_ext/date_and_time/calculations' +require 'active_support/deprecation' class Time include DateAndTime::Calculations @@ -25,10 +26,13 @@ class Time end end + # *DEPRECATED*: Use +Time#utc+ or +Time#local+ instead. + # # Returns a new Time if requested year can be accommodated by Ruby's Time class # (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture); # otherwise returns a DateTime. def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0) + ActiveSupport::Deprecation.warn 'time_with_datetime_fallback is deprecated. Use Time#utc or Time#local instead', caller time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec) # This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138. @@ -41,13 +45,19 @@ class Time ::DateTime.civil_from_format(utc_or_local, year, month, day, hour, min, sec) end + # *DEPRECATED*: Use +Time#utc+ instead. + # # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>. def utc_time(*args) + ActiveSupport::Deprecation.warn 'utc_time is deprecated. Use Time#utc instead', caller time_with_datetime_fallback(:utc, *args) end + # *DEPRECATED*: Use +Time#local+ instead. + # # Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>. def local_time(*args) + ActiveSupport::Deprecation.warn 'local_time is deprecated. Use Time#local instead', caller time_with_datetime_fallback(:local, *args) end @@ -160,6 +170,7 @@ class Time :usec => Rational(999999999, 1000) ) end + alias :at_end_of_day :end_of_day # Returns a new Time representing the start of the hour (x:00) def beginning_of_hour @@ -175,6 +186,7 @@ class Time :usec => Rational(999999999, 1000) ) end + alias :at_end_of_hour :end_of_hour # Returns a Range representing the whole day of the current time. def all_day diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index 17e69c34a5..485dc91063 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -30,7 +30,7 @@ module ActiveSupport # @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!") # @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!", deprecator_instance) # - # When someone execute any method expect +inspect+ on proxy object this will + # When someone executes any method except +inspect+ on proxy object this will # trigger +warn+ method on +deprecator_instance+. # # Default deprecator is <tt>ActiveSupport::Deprecation</tt> diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 7e99646117..2cb1f408b6 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -1,4 +1,4 @@ -require 'active_support/basic_object' +require 'active_support/proxy_object' require 'active_support/core_ext/array/conversions' require 'active_support/core_ext/object/acts_like' @@ -7,7 +7,7 @@ module ActiveSupport # Time#advance, respectively. It mainly supports the methods on Numeric. # # 1.month.ago # equivalent to Time.now.advance(months: -1) - class Duration < BasicObject + class Duration < ProxyObject attr_accessor :value, :parts def initialize(value, parts) #:nodoc: diff --git a/activesupport/lib/active_support/proxy_object.rb b/activesupport/lib/active_support/proxy_object.rb new file mode 100644 index 0000000000..a2bdf1d790 --- /dev/null +++ b/activesupport/lib/active_support/proxy_object.rb @@ -0,0 +1,13 @@ +module ActiveSupport + # A class with no predefined methods that behaves similarly to Builder's + # BlankSlate. Used for proxy classes. + class ProxyObject < ::BasicObject + undef_method :== + undef_method :equal? + + # Let ActiveSupport::BasicObject at least raise exceptions. + def raise(*args) + ::Object.send(:raise, *args) + end + end +end diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index bcd5d78b54..92a593965e 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -9,21 +9,12 @@ end require 'date' require 'time' -require 'active_support/core_ext/time/marshal' -require 'active_support/core_ext/time/acts_like' -require 'active_support/core_ext/time/calculations' -require 'active_support/core_ext/time/conversions' -require 'active_support/core_ext/time/zones' - -require 'active_support/core_ext/date/acts_like' -require 'active_support/core_ext/date/calculations' -require 'active_support/core_ext/date/conversions' -require 'active_support/core_ext/date/zones' - -require 'active_support/core_ext/date_time/acts_like' -require 'active_support/core_ext/date_time/calculations' -require 'active_support/core_ext/date_time/conversions' -require 'active_support/core_ext/date_time/zones' +require 'active_support/core_ext/time' +require 'active_support/core_ext/date' +require 'active_support/core_ext/date_time' require 'active_support/core_ext/integer/time' require 'active_support/core_ext/numeric/time' + +require 'active_support/core_ext/string/conversions' +require 'active_support/core_ext/string/zones' diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index b931de3fac..0dbc198ea2 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -344,7 +344,7 @@ module ActiveSupport end def transfer_time_values_to_utc_constructor(time) - ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:nsec) ? Rational(time.nsec, 1000) : 0) + ::Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec, Rational(time.nsec, 1000)) end def duration_of_variable_length?(obj) diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index d087955587..c5fbddcb5f 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -252,7 +252,7 @@ module ActiveSupport # Time.zone = 'Hawaii' # => "Hawaii" # Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00 def local(*args) - time = Time.utc_time(*args) + time = Time.utc(*args) ActiveSupport::TimeWithZone.new(nil, self, time) end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 7ae1f67785..5e89a6e00b 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -34,7 +34,7 @@ class DateExtCalculationsTest < ActiveSupport::TestCase def test_to_time assert_equal Time.local(2005, 2, 21), Date.new(2005, 2, 21).to_time - assert_equal Time.local_time(2039, 2, 21), Date.new(2039, 2, 21).to_time + assert_equal Time.local(2039, 2, 21), Date.new(2039, 2, 21).to_time silence_warnings do 0.upto(138) do |year| [:utc, :local].each do |format| @@ -354,3 +354,11 @@ class DateExtBehaviorTest < ActiveSupport::TestCase end end end + +class DateExtConversionsTest < ActiveSupport::TestCase + def test_to_time_in_current_zone_is_deprecated + assert_deprecated(/to_time_in_current_zone/) do + Date.new(2012,6,7).to_time_in_current_zone + end + end +end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 3353465c1c..dfad3a90f8 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -42,7 +42,7 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase def test_to_time assert_equal Time.utc(2005, 2, 21, 10, 11, 12), DateTime.new(2005, 2, 21, 10, 11, 12, 0).to_time - assert_equal Time.utc_time(2039, 2, 21, 10, 11, 12), DateTime.new(2039, 2, 21, 10, 11, 12, 0).to_time + assert_equal Time.utc(2039, 2, 21, 10, 11, 12), DateTime.new(2039, 2, 21, 10, 11, 12, 0).to_time # DateTimes with offsets other than 0 are returned unaltered assert_equal DateTime.new(2005, 2, 21, 10, 11, 12, Rational(-5, 24)), DateTime.new(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).to_time # Fractional seconds are preserved diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index c8312aa653..2826f51f2d 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -21,7 +21,7 @@ class DurationTest < ActiveSupport::TestCase assert ActiveSupport::Duration === 1.day assert !(ActiveSupport::Duration === 1.day.to_i) assert !(ActiveSupport::Duration === 'foo') - assert !(ActiveSupport::Duration === ActiveSupport::BasicObject.new) + assert !(ActiveSupport::Duration === ActiveSupport::ProxyObject.new) end def test_equals @@ -131,7 +131,7 @@ class DurationTest < ActiveSupport::TestCase assert_equal Time.local(2009,3,29,0,0,0) + 1.day, Time.local(2009,3,30,0,0,0) end end - + def test_delegation_with_block_works counter = 0 assert_nothing_raised do diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index 6720ed42f0..fa8839bcb3 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -161,30 +161,6 @@ class StringInflectionsTest < ActiveSupport::TestCase assert_equal 97, 'abc'.ord end - def test_string_to_time - assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time - assert_equal Time.local(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time(:local) - assert_equal Time.utc(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time - assert_equal Time.local(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time(:local) - assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time - assert_equal Time.local_time(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time(:local) - assert_equal Time.utc(2011, 2, 27, 23, 50), "2011-02-27 22:50 -0100".to_time - assert_nil "".to_time - end - - def test_string_to_datetime - assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_datetime - assert_equal 0, "2039-02-27 23:50".to_datetime.offset # use UTC offset - assert_equal ::Date::ITALY, "2039-02-27 23:50".to_datetime.start # use Ruby's default start value - assert_equal DateTime.civil(2039, 2, 27, 23, 50, 19 + Rational(275038, 1000000), "-04:00"), "2039-02-27T23:50:19.275038-04:00".to_datetime - assert_nil "".to_datetime - end - - def test_string_to_date - assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date - assert_nil "".to_date - end - def test_access s = "hello" assert_equal "h", s.at(0) @@ -308,6 +284,32 @@ class StringInflectionsTest < ActiveSupport::TestCase end end +class StringConversionsTest < ActiveSupport::TestCase + def test_string_to_time + assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time + assert_equal Time.local(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time(:local) + assert_equal Time.utc(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time + assert_equal Time.local(2005, 2, 27, 23, 50, 19, 275038), "2005-02-27T23:50:19.275038".to_time(:local) + assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time + assert_equal Time.local(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_time(:local) + assert_equal Time.utc(2011, 2, 27, 23, 50), "2011-02-27 22:50 -0100".to_time + assert_nil "".to_time + end + + def test_string_to_datetime + assert_equal DateTime.civil(2039, 2, 27, 23, 50), "2039-02-27 23:50".to_datetime + assert_equal 0, "2039-02-27 23:50".to_datetime.offset # use UTC offset + assert_equal ::Date::ITALY, "2039-02-27 23:50".to_datetime.start # use Ruby's default start value + assert_equal DateTime.civil(2039, 2, 27, 23, 50, 19 + Rational(275038, 1000000), "-04:00"), "2039-02-27T23:50:19.275038-04:00".to_datetime + assert_nil "".to_datetime + end + + def test_string_to_date + assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date + assert_nil "".to_date + end +end + class StringBehaviourTest < ActiveSupport::TestCase def test_acts_like_string assert 'Bambi'.acts_like_string? diff --git a/activesupport/test/core_ext/thread_test.rb b/activesupport/test/core_ext/thread_test.rb new file mode 100644 index 0000000000..b58f59a8d4 --- /dev/null +++ b/activesupport/test/core_ext/thread_test.rb @@ -0,0 +1,77 @@ +require 'abstract_unit' +require 'active_support/core_ext/thread' + +class ThreadExt < ActiveSupport::TestCase + def test_main_thread_variable_in_enumerator + assert_equal Thread.main, Thread.current + + Thread.current.thread_variable_set :foo, "bar" + + thread, value = Fiber.new { + Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] + }.resume + + assert_equal Thread.current, thread + assert_equal Thread.current.thread_variable_get(:foo), value + end + + def test_thread_variable_in_enumerator + Thread.new { + Thread.current.thread_variable_set :foo, "bar" + + thread, value = Fiber.new { + Fiber.yield [Thread.current, Thread.current.thread_variable_get(:foo)] + }.resume + + assert_equal Thread.current, thread + assert_equal Thread.current.thread_variable_get(:foo), value + }.join + end + + def test_thread_variables + assert_equal [], Thread.new { Thread.current.thread_variables }.join.value + + t = Thread.new { + Thread.current.thread_variable_set(:foo, "bar") + Thread.current.thread_variables + } + assert_equal [:foo], t.join.value + end + + def test_thread_variable? + refute Thread.new { Thread.current.thread_variable?("foo") }.join.value + t = Thread.new { + Thread.current.thread_variable_set("foo", "bar") + }.join + + assert t.thread_variable?("foo") + assert t.thread_variable?(:foo) + refute t.thread_variable?(:bar) + end + + def test_thread_variable_strings_and_symbols_are_the_same_key + t = Thread.new {}.join + t.thread_variable_set("foo", "bar") + assert_equal "bar", t.thread_variable_get(:foo) + end + + def test_thread_variable_frozen + t = Thread.new { }.join + t.freeze + assert_raises(RuntimeError) do + t.thread_variable_set(:foo, "bar") + end + end + + def test_thread_variable_security + t = Thread.new { sleep } + + assert_raises(SecurityError) do + Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join + end + + assert_raises(SecurityError) do + Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join + end + end +end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 0e75104fc6..70e07cefd1 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -567,45 +567,57 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_time_with_datetime_fallback - assert_equal Time.time_with_datetime_fallback(:utc, 2005, 2, 21, 17, 44, 30), Time.utc(2005, 2, 21, 17, 44, 30) - assert_equal Time.time_with_datetime_fallback(:local, 2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30) - assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, 0) - assert_equal Time.time_with_datetime_fallback(:local, 2039, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 2039, 2, 21, 17, 44, 30) - assert_equal Time.time_with_datetime_fallback(:utc, 1900, 2, 21, 17, 44, 30), DateTime.civil(1900, 2, 21, 17, 44, 30, 0) - assert_equal Time.time_with_datetime_fallback(:utc, 2005), Time.utc(2005) - assert_equal Time.time_with_datetime_fallback(:utc, 2039), DateTime.civil(2039, 1, 1, 0, 0, 0, 0) - assert_equal Time.time_with_datetime_fallback(:utc, 2005, 2, 21, 17, 44, 30, 1), Time.utc(2005, 2, 21, 17, 44, 30, 1) #with usec - # This won't overflow on 64bit linux - unless time_is_64bits? - assert_equal Time.time_with_datetime_fallback(:local, 1900, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 1900, 2, 21, 17, 44, 30) - assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1), - DateTime.civil(2039, 2, 21, 17, 44, 30, 0, 0) - assert_equal ::Date::ITALY, Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1).start # use Ruby's default start value - end - silence_warnings do - 0.upto(138) do |year| - [:utc, :local].each do |format| - assert_equal year, Time.time_with_datetime_fallback(format, year).year + ActiveSupport::Deprecation.silence do + assert_equal Time.time_with_datetime_fallback(:utc, 2005, 2, 21, 17, 44, 30), Time.utc(2005, 2, 21, 17, 44, 30) + assert_equal Time.time_with_datetime_fallback(:local, 2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30) + assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, 0) + assert_equal Time.time_with_datetime_fallback(:local, 2039, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 2039, 2, 21, 17, 44, 30) + assert_equal Time.time_with_datetime_fallback(:utc, 1900, 2, 21, 17, 44, 30), DateTime.civil(1900, 2, 21, 17, 44, 30, 0) + assert_equal Time.time_with_datetime_fallback(:utc, 2005), Time.utc(2005) + assert_equal Time.time_with_datetime_fallback(:utc, 2039), DateTime.civil(2039, 1, 1, 0, 0, 0, 0) + assert_equal Time.time_with_datetime_fallback(:utc, 2005, 2, 21, 17, 44, 30, 1), Time.utc(2005, 2, 21, 17, 44, 30, 1) #with usec + # This won't overflow on 64bit linux + unless time_is_64bits? + assert_equal Time.time_with_datetime_fallback(:local, 1900, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 1900, 2, 21, 17, 44, 30) + assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1), + DateTime.civil(2039, 2, 21, 17, 44, 30, 0, 0) + assert_equal ::Date::ITALY, Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1).start # use Ruby's default start value + end + silence_warnings do + 0.upto(138) do |year| + [:utc, :local].each do |format| + assert_equal year, Time.time_with_datetime_fallback(format, year).year + end end end end end def test_utc_time - assert_equal Time.utc_time(2005, 2, 21, 17, 44, 30), Time.utc(2005, 2, 21, 17, 44, 30) - assert_equal Time.utc_time(2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, 0) - assert_equal Time.utc_time(1901, 2, 21, 17, 44, 30), DateTime.civil(1901, 2, 21, 17, 44, 30, 0) + ActiveSupport::Deprecation.silence do + assert_equal Time.utc_time(2005, 2, 21, 17, 44, 30), Time.utc(2005, 2, 21, 17, 44, 30) + assert_equal Time.utc_time(2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, 0) + assert_equal Time.utc_time(1901, 2, 21, 17, 44, 30), DateTime.civil(1901, 2, 21, 17, 44, 30, 0) + end end def test_local_time - assert_equal Time.local_time(2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30) - assert_equal Time.local_time(2039, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 2039, 2, 21, 17, 44, 30) + ActiveSupport::Deprecation.silence do + assert_equal Time.local_time(2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30) + assert_equal Time.local_time(2039, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 2039, 2, 21, 17, 44, 30) - unless time_is_64bits? - assert_equal Time.local_time(1901, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 1901, 2, 21, 17, 44, 30) + unless time_is_64bits? + assert_equal Time.local_time(1901, 2, 21, 17, 44, 30), DateTime.civil_from_format(:local, 1901, 2, 21, 17, 44, 30) + end end end + def test_time_with_datetime_fallback_deprecations + assert_deprecated(/time_with_datetime_fallback/) { Time.time_with_datetime_fallback(:utc, 2012, 6, 7) } + assert_deprecated(/utc_time/) { Time.utc_time(2012, 6, 7) } + assert_deprecated(/local_time/) { Time.local_time(2012, 6, 7) } + end + def test_last_month_on_31st assert_equal Time.local(2004, 2, 29), Time.local(2004, 3, 31).last_month end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 1293f104e5..56020da035 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -953,3 +953,131 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') end end + +class TimeWithZoneMethodsForDate < ActiveSupport::TestCase + def setup + @d = Date.civil(2000) + end + + def teardown + Time.zone = nil + end + + def test_in_time_zone + with_tz_default 'Alaska' do + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @d.in_time_zone.inspect + end + with_tz_default 'Hawaii' do + assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @d.in_time_zone.inspect + end + with_tz_default nil do + assert_equal @d.to_time, @d.in_time_zone + end + end + + def test_nil_time_zone + with_tz_default nil do + assert !@d.in_time_zone.respond_to?(:period), 'no period method' + end + end + + def test_in_time_zone_with_argument + with_tz_default 'Eastern Time (US & Canada)' do # Time.zone will not affect #in_time_zone(zone) + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @d.in_time_zone('Alaska').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @d.in_time_zone('Hawaii').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 UTC +00:00', @d.in_time_zone('UTC').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @d.in_time_zone(-9.hours).inspect + end + end + + def test_in_time_zone_with_invalid_argument + assert_raise(ArgumentError) { @d.in_time_zone("No such timezone exists") } + assert_raise(ArgumentError) { @d.in_time_zone(-15.hours) } + assert_raise(ArgumentError) { @d.in_time_zone(Object.new) } + end + + protected + def with_tz_default(tz = nil) + old_tz = Time.zone + Time.zone = tz + yield + ensure + Time.zone = old_tz + end +end + +class TimeWithZoneMethodsForString < ActiveSupport::TestCase + def setup + @s = "Sat, 01 Jan 2000 00:00:00" + @u = "Sat, 01 Jan 2000 00:00:00 UTC +00:00" + @z = "Fri, 31 Dec 1999 19:00:00 EST -05:00" + end + + def teardown + Time.zone = nil + end + + def test_in_time_zone + with_tz_default 'Alaska' do + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @s.in_time_zone.inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @u.in_time_zone.inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @z.in_time_zone.inspect + end + with_tz_default 'Hawaii' do + assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @s.in_time_zone.inspect + assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @u.in_time_zone.inspect + assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @z.in_time_zone.inspect + end + with_tz_default nil do + assert_equal @s.to_time, @s.in_time_zone + assert_equal @u.to_time, @u.in_time_zone + assert_equal @z.to_time, @z.in_time_zone + end + end + + def test_nil_time_zone + with_tz_default nil do + assert !@s.in_time_zone.respond_to?(:period), 'no period method' + assert !@u.in_time_zone.respond_to?(:period), 'no period method' + assert !@z.in_time_zone.respond_to?(:period), 'no period method' + end + end + + def test_in_time_zone_with_argument + with_tz_default 'Eastern Time (US & Canada)' do # Time.zone will not affect #in_time_zone(zone) + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @s.in_time_zone('Alaska').inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @u.in_time_zone('Alaska').inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @z.in_time_zone('Alaska').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @s.in_time_zone('Hawaii').inspect + assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @u.in_time_zone('Hawaii').inspect + assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @z.in_time_zone('Hawaii').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 UTC +00:00', @s.in_time_zone('UTC').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 UTC +00:00', @u.in_time_zone('UTC').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 UTC +00:00', @z.in_time_zone('UTC').inspect + assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @s.in_time_zone(-9.hours).inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @u.in_time_zone(-9.hours).inspect + assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @z.in_time_zone(-9.hours).inspect + end + end + + def test_in_time_zone_with_invalid_argument + assert_raise(ArgumentError) { @s.in_time_zone("No such timezone exists") } + assert_raise(ArgumentError) { @u.in_time_zone("No such timezone exists") } + assert_raise(ArgumentError) { @z.in_time_zone("No such timezone exists") } + assert_raise(ArgumentError) { @s.in_time_zone(-15.hours) } + assert_raise(ArgumentError) { @u.in_time_zone(-15.hours) } + assert_raise(ArgumentError) { @z.in_time_zone(-15.hours) } + assert_raise(ArgumentError) { @s.in_time_zone(Object.new) } + assert_raise(ArgumentError) { @u.in_time_zone(Object.new) } + assert_raise(ArgumentError) { @z.in_time_zone(Object.new) } + end + + protected + def with_tz_default(tz = nil) + old_tz = Time.zone + Time.zone = tz + yield + ensure + Time.zone = old_tz + end +end diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb index 952c82f9d8..51a7e4b2fe 100644 --- a/activesupport/test/dependencies_test.rb +++ b/activesupport/test/dependencies_test.rb @@ -923,8 +923,10 @@ class DependenciesTest < ActiveSupport::TestCase def test_remove_constant_does_not_autoload_already_removed_parents_as_a_side_effect with_autoloading_fixtures do - ::A - ::A::B + silence_warnings do + ::A + ::A::B + end ActiveSupport::Dependencies.remove_constant('A') ActiveSupport::Dependencies.remove_constant('A::B') assert !defined?(A) @@ -934,7 +936,9 @@ class DependenciesTest < ActiveSupport::TestCase def test_load_once_constants_should_not_be_unloaded with_autoloading_fixtures do ActiveSupport::Dependencies.autoload_once_paths = ActiveSupport::Dependencies.autoload_paths - ::A.to_s + silence_warnings do + ::A + end assert defined?(A) ActiveSupport::Dependencies.clear assert defined?(A) |