diff options
Diffstat (limited to 'activesupport')
21 files changed, 182 insertions, 61 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 82921741b8..b02cefa600 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* `deep_dup` works more expectedly now and duplicates also values in +Hash+ instances and elements in +Array+ instances. *Alexey Gaziev* + * Inflector no longer applies ice -> ouse to words like slice, police, ets *Wes Morgan* * Add `ActiveSupport::Deprecations.behavior = :silence` to completely ignore Rails runtime deprecations *twinturbo* diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb index dbf0c25c5c..8f018dcbc6 100644 --- a/activesupport/lib/active_support.rb +++ b/activesupport/lib/active_support.rb @@ -22,20 +22,6 @@ #++ require 'securerandom' - -module ActiveSupport - class << self - attr_accessor :load_all_hooks - def on_load_all(&hook) load_all_hooks << hook end - def load_all!; load_all_hooks.each { |hook| hook.call } end - end - self.load_all_hooks = [] - - on_load_all do - [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte] - end -end - require "active_support/dependencies/autoload" require "active_support/version" require "active_support/logger" @@ -44,6 +30,7 @@ module ActiveSupport extend ActiveSupport::Autoload autoload :Concern + autoload :Dependencies autoload :DescendantsTracker autoload :FileUpdateChecker autoload :LogSubscriber 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 0e5aa5af10..020fa1a06d 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -91,6 +91,17 @@ class DateTime change(:hour => 23, :min => 59, :sec => 59) end + # Returns a new DateTime representing the start of the hour (hh:00:00) + def beginning_of_hour + change(:min => 0) + end + alias :at_beginning_of_hour :beginning_of_hour + + # Returns a new DateTime representing the end of the hour (hh:59:59) + def end_of_hour + change(:min => 59, :sec => 59) + end + # Adjusts DateTime to UTC by adding its offset value; offset is set to 0 # # Example: diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb index fd1cda991e..501483498d 100644 --- a/activesupport/lib/active_support/core_ext/hash.rb +++ b/activesupport/lib/active_support/core_ext/hash.rb @@ -1,6 +1,5 @@ require 'active_support/core_ext/hash/conversions' require 'active_support/core_ext/hash/deep_merge' -require 'active_support/core_ext/hash/deep_dup' require 'active_support/core_ext/hash/diff' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/indifferent_access' diff --git a/activesupport/lib/active_support/core_ext/hash/deep_dup.rb b/activesupport/lib/active_support/core_ext/hash/deep_dup.rb deleted file mode 100644 index 9ab179c566..0000000000 --- a/activesupport/lib/active_support/core_ext/hash/deep_dup.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Hash - # Returns a deep copy of hash. - def deep_dup - duplicate = self.dup - duplicate.each_pair do |k,v| - duplicate[k] = v.is_a?(Hash) ? v.deep_dup : v - end - duplicate - end -end diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb index 822f766af7..2bf3d1f278 100644 --- a/activesupport/lib/active_support/core_ext/numeric/time.rb +++ b/activesupport/lib/active_support/core_ext/numeric/time.rb @@ -8,13 +8,13 @@ class Numeric # These methods use Time#advance for precise date calculations when using from_now, ago, etc. # as well as adding or subtracting their results from a Time object. For example: # - # # equivalent to Time.now.advance(:months => 1) + # # equivalent to Time.current.advance(:months => 1) # 1.month.from_now # - # # equivalent to Time.now.advance(:years => 2) + # # equivalent to Time.current.advance(:years => 2) # 2.years.from_now # - # # equivalent to Time.now.advance(:months => 4, :years => 5) + # # equivalent to Time.current.advance(:months => 4, :years => 5) # (4.months + 5.years).from_now # # While these methods provide precise calculation when used as in the examples above, care diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb index 9ad1e12699..ec2157221f 100644 --- a/activesupport/lib/active_support/core_ext/object.rb +++ b/activesupport/lib/active_support/core_ext/object.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/duplicable' +require 'active_support/core_ext/object/deep_dup' require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/inclusion' diff --git a/activesupport/lib/active_support/core_ext/object/deep_dup.rb b/activesupport/lib/active_support/core_ext/object/deep_dup.rb new file mode 100644 index 0000000000..2c4383ac94 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/object/deep_dup.rb @@ -0,0 +1,22 @@ +class Object + # Returns a deep copy of object if it's duplicable. + def deep_dup + duplicable? ? dup : self + end +end + +class Array + # Returns a deep copy of array. + def deep_dup + map { |it| it.deep_dup } + end +end + +class Hash + # Returns a deep copy of hash. + def deep_dup + each_with_object(dup) do |(key, value), hash| + hash[key.deep_dup] = value.deep_dup + end + end +end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 1434e186c3..a0f610d60c 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -257,6 +257,21 @@ class Time ) end + # Returns a new Time representing the start of the hour (x:00) + def beginning_of_hour + change(:min => 0) + end + alias :at_beginning_of_hour :beginning_of_hour + + # Returns a new Time representing the end of the hour, x:59:59.999999 (.999999999 in ruby1.9) + def end_of_hour + change( + :min => 59, + :sec => 59, + :usec => 999999.999 + ) + end + # Returns a new Time representing the start of the month (1st of the month, 0:00) def beginning_of_month #self - ((self.mday-1).days + self.seconds_since_midnight) diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 9a748dfa60..b20c980f36 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -62,8 +62,8 @@ module ActiveSupport #:nodoc: # Returns +true+ if _obj_ responds to the given method. Private methods are included in the search # only if the optional second parameter evaluates to +true+. - def respond_to?(method, include_private=false) - super || @wrapped_string.respond_to?(method, include_private) + def respond_to_missing?(method, include_private) + @wrapped_string.respond_to?(method, include_private) end # Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise. diff --git a/activesupport/lib/active_support/ordered_options.rb b/activesupport/lib/active_support/ordered_options.rb index 538e41e0eb..60e6cd55ad 100644 --- a/activesupport/lib/active_support/ordered_options.rb +++ b/activesupport/lib/active_support/ordered_options.rb @@ -36,7 +36,7 @@ module ActiveSupport #:nodoc: end end - def respond_to?(name) + def respond_to_missing?(name, include_private) true end end diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index 9634b52ecf..bcd5d78b54 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -4,10 +4,6 @@ module ActiveSupport autoload :Duration, 'active_support/duration' autoload :TimeWithZone, 'active_support/time_with_zone' autoload :TimeZone, 'active_support/values/time_zone' - - on_load_all do - [Duration, TimeWithZone, TimeZone] - end end require 'date' diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 9d89e425fc..cd07c24257 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -313,10 +313,10 @@ module ActiveSupport end # Ensure proxy class responds to all methods that underlying time instance responds to. - def respond_to?(sym, include_priv = false) + def respond_to_missing?(sym, include_priv) # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime - return false if sym.to_s == 'acts_like_date?' - super || time.respond_to?(sym, include_priv) + return false if sym.to_sym == :acts_like_date? + time.respond_to?(sym, include_priv) end # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+. diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index cd8cb5d18b..3da0825489 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -91,6 +91,14 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2005,2,4,23,59,59), DateTime.civil(2005,2,4,10,10,10).end_of_day end + def test_beginning_of_hour + assert_equal DateTime.civil(2005,2,4,19,0,0), DateTime.civil(2005,2,4,19,30,10).beginning_of_hour + end + + def test_end_of_hour + assert_equal DateTime.civil(2005,2,4,19,59,59), DateTime.civil(2005,2,4,19,30,10).end_of_hour + end + def test_beginning_of_month assert_equal DateTime.civil(2005,2,1,0,0,0), DateTime.civil(2005,2,22,10,10,10).beginning_of_month end diff --git a/activesupport/test/core_ext/deep_dup_test.rb b/activesupport/test/core_ext/deep_dup_test.rb new file mode 100644 index 0000000000..91d558dbb5 --- /dev/null +++ b/activesupport/test/core_ext/deep_dup_test.rb @@ -0,0 +1,53 @@ +require 'abstract_unit' +require 'active_support/core_ext/object' + +class DeepDupTest < ActiveSupport::TestCase + + def test_array_deep_dup + array = [1, [2, 3]] + dup = array.deep_dup + dup[1][2] = 4 + assert_equal nil, array[1][2] + assert_equal 4, dup[1][2] + end + + def test_hash_deep_dup + hash = { :a => { :b => 'b' } } + dup = hash.deep_dup + dup[:a][:c] = 'c' + assert_equal nil, hash[:a][:c] + assert_equal 'c', dup[:a][:c] + end + + def test_array_deep_dup_with_hash_inside + array = [1, { :a => 2, :b => 3 } ] + dup = array.deep_dup + dup[1][:c] = 4 + assert_equal nil, array[1][:c] + assert_equal 4, dup[1][:c] + end + + def test_hash_deep_dup_with_array_inside + hash = { :a => [1, 2] } + dup = hash.deep_dup + dup[:a][2] = 'c' + assert_equal nil, hash[:a][2] + assert_equal 'c', dup[:a][2] + end + + def test_deep_dup_initialize + zero_hash = Hash.new 0 + hash = { :a => zero_hash } + dup = hash.deep_dup + assert_equal 0, dup[:a][44] + end + + def test_object_deep_dup + object = Object.new + dup = object.deep_dup + dup.instance_variable_set(:@a, 1) + assert !object.instance_variable_defined?(:@a) + assert dup.instance_variable_defined?(:@a) + end + +end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 80b3c16328..1cd10eb6e2 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -363,21 +363,6 @@ class HashExtTest < ActiveSupport::TestCase assert_equal expected, hash_1 end - def test_deep_dup - hash = { :a => { :b => 'b' } } - dup = hash.deep_dup - dup[:a][:c] = 'c' - assert_equal nil, hash[:a][:c] - assert_equal 'c', dup[:a][:c] - end - - def test_deep_dup_initialize - zero_hash = Hash.new 0 - hash = { :a => zero_hash } - dup = hash.deep_dup - assert_equal 0, dup[:a][44] - end - def test_store_on_indifferent_access hash = HashWithIndifferentAccess.new hash.store(:test1, 1) diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb index cf1ec448c2..9c3389ba82 100644 --- a/activesupport/test/core_ext/range_ext_test.rb +++ b/activesupport/test/core_ext/range_ext_test.rb @@ -41,6 +41,18 @@ class RangeTest < ActiveSupport::TestCase assert((1..10).include?(1...10)) end + def test_should_compare_identical_inclusive + assert((1..10) === (1..10)) + end + + def test_should_compare_identical_exclusive + assert((1...10) === (1...10)) + end + + def test_should_compare_other_with_exlusive_end + assert((1..10) === (1...10)) + end + def test_exclusive_end_should_not_include_identical_with_inclusive_end assert !(1...10).include?(1..10) end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index c542acca68..4c1ed4b1ae 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -93,6 +93,10 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end + def test_beginning_of_hour + assert_equal Time.local(2005,2,4,19,0,0), Time.local(2005,2,4,19,30,10).beginning_of_hour + end + def test_beginning_of_month assert_equal Time.local(2005,2,1,0,0,0), Time.local(2005,2,22,10,10,10).beginning_of_month end @@ -127,6 +131,10 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase assert_equal Time.local(2007,9,2,23,59,59,999999.999), Time.local(2007,9,02,0,0,0).end_of_week #sunday end + def test_end_of_hour + assert_equal Time.local(2005,2,4,19,59,59,999999.999), Time.local(2005,2,4,19,30,10).end_of_hour + end + def test_end_of_month assert_equal Time.local(2005,3,31,23,59,59,999999.999), Time.local(2005,3,20,10,10,10).end_of_month assert_equal Time.local(2005,2,28,23,59,59,999999.999), Time.local(2005,2,20,10,10,10).end_of_month diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 7cf3842a16..b62337e31b 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -191,7 +191,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase end end - def future_with_time_current_as_time_with_zone + def test_future_with_time_current_as_time_with_zone twz = ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45) ) Time.stubs(:current).returns(twz) assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? @@ -450,6 +450,7 @@ class TimeWithZoneTest < ActiveSupport::TestCase def test_ruby_19_weekday_name_query_methods %w(sunday? monday? tuesday? wednesday? thursday? friday? saturday?).each do |name| assert_respond_to @twz, name + assert_equal @twz.send(name), @twz.method(name).call end end @@ -482,36 +483,50 @@ class TimeWithZoneTest < ActiveSupport::TestCase assert_equal "Fri, 31 Dec 1999 19:00:30 EST -05:00", @twz.advance(:seconds => 30).inspect end - def beginning_of_year + def test_beginning_of_year assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect assert_equal "Fri, 01 Jan 1999 00:00:00 EST -05:00", @twz.beginning_of_year.inspect end - def end_of_year + def test_end_of_year assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect assert_equal "Fri, 31 Dec 1999 23:59:59 EST -05:00", @twz.end_of_year.inspect end - def beginning_of_month + def test_beginning_of_month assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect - assert_equal "Fri, 01 Dec 1999 00:00:00 EST -05:00", @twz.beginning_of_month.inspect + assert_equal "Wed, 01 Dec 1999 00:00:00 EST -05:00", @twz.beginning_of_month.inspect end - def end_of_month + def test_end_of_month assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect assert_equal "Fri, 31 Dec 1999 23:59:59 EST -05:00", @twz.end_of_month.inspect end - def beginning_of_day + def test_beginning_of_day assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect assert_equal "Fri, 31 Dec 1999 00:00:00 EST -05:00", @twz.beginning_of_day.inspect end - def end_of_day + def test_end_of_day assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", @twz.inspect assert_equal "Fri, 31 Dec 1999 23:59:59 EST -05:00", @twz.end_of_day.inspect end + def test_beginning_of_hour + utc = Time.utc(2000, 1, 1, 0, 30) + twz = ActiveSupport::TimeWithZone.new(utc, @time_zone) + assert_equal "Fri, 31 Dec 1999 19:30:00 EST -05:00", twz.inspect + assert_equal "Fri, 31 Dec 1999 19:00:00 EST -05:00", twz.beginning_of_hour.inspect + end + + def test_end_of_hour + utc = Time.utc(2000, 1, 1, 0, 30) + twz = ActiveSupport::TimeWithZone.new(utc, @time_zone) + assert_equal "Fri, 31 Dec 1999 19:30:00 EST -05:00", twz.inspect + assert_equal "Fri, 31 Dec 1999 19:59:59 EST -05:00", twz.end_of_hour.inspect + end + def test_since assert_equal "Fri, 31 Dec 1999 19:00:01 EST -05:00", @twz.since(1).inspect end diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb index 90aa13b3e6..a8d69d0ec3 100644 --- a/activesupport/test/multibyte_chars_test.rb +++ b/activesupport/test/multibyte_chars_test.rb @@ -458,6 +458,15 @@ class MultibyteCharsUTF8BehaviourTest < ActiveSupport::TestCase assert !''.mb_chars.respond_to?(:undefined_method) # Not defined end + def test_method_works_for_proxyed_methods + assert_equal 'll', 'hello'.mb_chars.method(:slice).call(2..3) # Defined on Chars + chars = 'hello'.mb_chars + assert_equal 'Hello', chars.method(:capitalize!).call # Defined on Chars + assert_equal 'Hello', chars + assert_equal 'jello', 'hello'.mb_chars.method(:gsub).call(/h/, 'j') # Defined on String + assert_raise(NameError){ ''.mb_chars.method(:undefined_method) } # Not defined + end + def test_acts_like_string assert 'Bambi'.mb_chars.acts_like_string? end diff --git a/activesupport/test/ordered_options_test.rb b/activesupport/test/ordered_options_test.rb index 3526c7a366..f60f9a58e3 100644 --- a/activesupport/test/ordered_options_test.rb +++ b/activesupport/test/ordered_options_test.rb @@ -77,4 +77,12 @@ class OrderedOptionsTest < ActiveSupport::TestCase assert copy.kind_of?(original.class) assert_not_equal copy.object_id, original.object_id end + + def test_introspection + a = ActiveSupport::OrderedOptions.new + assert a.respond_to?(:blah) + assert a.respond_to?(:blah=) + assert_equal 42, a.method(:blah=).call(42) + assert_equal 42, a.method(:blah).call + end end |