diff options
Diffstat (limited to 'activesupport/lib')
25 files changed, 220 insertions, 125 deletions
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb index 8253a76383..d0e53eaf05 100644 --- a/activesupport/lib/active_support/cache.rb +++ b/activesupport/lib/active_support/cache.rb @@ -277,13 +277,18 @@ module ActiveSupport options = merged_options(options) key = namespaced_key(name, options) - cached_entry = find_cached_entry(key, name, options) unless options[:force] - entry = handle_expired_entry(cached_entry, key, options) + instrument(:read, name, options) do |payload| + cached_entry = read_entry(key, options) unless options[:force] + payload[:super_operation] = :fetch if payload + entry = handle_expired_entry(cached_entry, key, options) - if entry - get_entry_value(entry, name, options) - else - save_block_result_to_cache(name, options) { |_name| yield _name } + if entry + payload[:hit] = true if payload + get_entry_value(entry, name, options) + else + payload[:hit] = false if payload + save_block_result_to_cache(name, options) { |_name| yield _name } + end end else read(name, options) @@ -533,7 +538,7 @@ module ActiveSupport end def instrument(operation, key, options = nil) - log { "Cache #{operation}: #{key}#{options.blank? ? "" : " (#{options.inspect})"}" } + log { "Cache #{operation}: #{namespaced_key(key, options)}#{options.blank? ? "" : " (#{options.inspect})"}" } payload = { :key => key } payload.merge!(options) if options.is_a?(Hash) @@ -556,13 +561,6 @@ module ActiveSupport logger.debug(yield) end - def find_cached_entry(key, name, options) - instrument(:read, name, options) do |payload| - payload[:super_operation] = :fetch if payload - read_entry(key, options) - end - end - def handle_expired_entry(entry, key, options) if entry && entry.expired? race_ttl = options[:race_condition_ttl].to_i diff --git a/activesupport/lib/active_support/cache/file_store.rb b/activesupport/lib/active_support/cache/file_store.rb index e6a8b84214..b7da30123a 100644 --- a/activesupport/lib/active_support/cache/file_store.rb +++ b/activesupport/lib/active_support/cache/file_store.rb @@ -119,11 +119,12 @@ module ActiveSupport # Translate a key into a file path. def key_file_path(key) - if key.size > FILEPATH_MAX_SIZE - key = Digest::MD5.hexdigest(key) + fname = URI.encode_www_form_component(key) + + if fname.size > FILEPATH_MAX_SIZE + fname = Digest::MD5.hexdigest(key) end - fname = URI.encode_www_form_component(key) hash = Zlib.adler32(fname) hash, dir_1 = hash.divmod(0x1000) dir_2 = hash.modulo(0x1000) diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 252374e817..d43fde03a9 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -748,15 +748,15 @@ module ActiveSupport protected - def get_callbacks(name) + def get_callbacks(name) # :nodoc: send "_#{name}_callbacks" end - def set_callbacks(name, callbacks) + def set_callbacks(name, callbacks) # :nodoc: send "_#{name}_callbacks=", callbacks end - def deprecated_false_terminator + def deprecated_false_terminator # :nodoc: Proc.new do |target, result_lambda| terminate = true catch(:abort) do diff --git a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb index 234283e792..22fc7ecf92 100644 --- a/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb +++ b/activesupport/lib/active_support/core_ext/big_decimal/conversions.rb @@ -1,15 +1,14 @@ require 'bigdecimal' require 'bigdecimal/util' -class BigDecimal - DEFAULT_STRING_FORMAT = 'F' - alias_method :to_default_s, :to_s +module ActiveSupport + module BigDecimalWithDefaultFormat #:nodoc: + DEFAULT_STRING_FORMAT = 'F' - def to_s(format = nil, options = nil) - if format.is_a?(Symbol) - to_formatted_s(format, options || {}) - else - to_default_s(format || DEFAULT_STRING_FORMAT) + def to_s(format = nil) + super(format || DEFAULT_STRING_FORMAT) end end end + +BigDecimal.prepend(ActiveSupport::BigDecimalWithDefaultFormat) diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index f2b7bb3ef1..802d988af2 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -75,11 +75,15 @@ class Class instance_predicate = options.fetch(:instance_predicate, true) attrs.each do |name| + remove_possible_singleton_method(name) define_singleton_method(name) { nil } + + remove_possible_singleton_method("#{name}?") define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate ivar = "@#{name}" + remove_possible_singleton_method("#{name}=") define_singleton_method("#{name}=") do |val| singleton_class.class_eval do remove_possible_method(name) @@ -110,10 +114,15 @@ class Class self.class.public_send name end end + + remove_possible_method "#{name}?" define_method("#{name}?") { !!public_send(name) } if instance_predicate end - attr_writer name if instance_writer + if instance_writer + remove_possible_method "#{name}=" + attr_writer name + end end end end diff --git a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb index 28cb3e2a3b..6df7b4121b 100644 --- a/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb +++ b/activesupport/lib/active_support/core_ext/hash/indifferent_access.rb @@ -6,7 +6,7 @@ class Hash # # { a: 1 }.with_indifferent_access['a'] # => 1 def with_indifferent_access - ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default(self) + ActiveSupport::HashWithIndifferentAccess.new(self) end # Called when object is nested under an object that receives diff --git a/activesupport/lib/active_support/core_ext/integer/time.rb b/activesupport/lib/active_support/core_ext/integer/time.rb index f0b7382ef3..87185b024f 100644 --- a/activesupport/lib/active_support/core_ext/integer/time.rb +++ b/activesupport/lib/active_support/core_ext/integer/time.rb @@ -23,7 +23,7 @@ class Integer alias :month :months def years - ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]]) + ActiveSupport::Duration.new(self * 365.25.days.to_i, [[:years, self]]) end alias :year :years end diff --git a/activesupport/lib/active_support/core_ext/module/anonymous.rb b/activesupport/lib/active_support/core_ext/module/anonymous.rb index 0ecc67a855..510c9a5430 100644 --- a/activesupport/lib/active_support/core_ext/module/anonymous.rb +++ b/activesupport/lib/active_support/core_ext/module/anonymous.rb @@ -7,7 +7,7 @@ class Module # m = Module.new # m.name # => nil # - # +anonymous?+ method returns true if module does not have a name: + # +anonymous?+ method returns true if module does not have a name, false otherwise: # # Module.new.anonymous? # => true # @@ -18,8 +18,10 @@ class Module # via the +module+ or +class+ keyword or by an explicit assignment: # # m = Module.new # creates an anonymous module - # M = m # => m gets a name here as a side-effect + # m.anonymous? # => true + # M = m # m gets a name here as a side-effect # m.name # => "M" + # m.anonymous? # => false def anonymous? name.nil? end diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 9dc0dee1bd..0d46248582 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -5,10 +5,11 @@ class Module # option is not used. class DelegationError < NoMethodError; end - RUBY_RESERVED_WORDS = Set.new( - %w(alias and BEGIN begin break case class def defined? do else elsif END - end ensure false for if in module next nil not or redo rescue retry - return self super then true undef unless until when while yield) + DELEGATION_RESERVED_METHOD_NAMES = Set.new( + %w(_ arg args alias and BEGIN begin block break case class def defined? do + else elsif END end ensure false for if in module next nil not or redo + rescue retry return self super then true undef unless until when while + yield) ).freeze # Provides a +delegate+ class method to easily expose contained objects' @@ -171,7 +172,7 @@ class Module line = line.to_i to = to.to_s - to = "self.#{to}" if RUBY_RESERVED_WORDS.include?(to) + to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to) methods.each do |method| # Attribute writer methods only accept one argument. Makes sure []= diff --git a/activesupport/lib/active_support/core_ext/module/remove_method.rb b/activesupport/lib/active_support/core_ext/module/remove_method.rb index 52632d2c6b..d5ec16d68a 100644 --- a/activesupport/lib/active_support/core_ext/module/remove_method.rb +++ b/activesupport/lib/active_support/core_ext/module/remove_method.rb @@ -6,10 +6,30 @@ class Module end end + # Removes the named singleton method, if it exists. + def remove_possible_singleton_method(method) + singleton_class.instance_eval do + remove_possible_method(method) + end + end + # Replaces the existing method definition, if there is one, with the passed # block as its body. def redefine_method(method, &block) + visibility = method_visibility(method) remove_possible_method(method) define_method(method, &block) + send(visibility, method) + end + + def method_visibility(method) # :nodoc: + case + when private_method_defined?(method) + :private + when protected_method_defined?(method) + :protected + else + :public + end end end diff --git a/activesupport/lib/active_support/core_ext/numeric/conversions.rb b/activesupport/lib/active_support/core_ext/numeric/conversions.rb index d5bb11deed..9a3651f29a 100644 --- a/activesupport/lib/active_support/core_ext/numeric/conversions.rb +++ b/activesupport/lib/active_support/core_ext/numeric/conversions.rb @@ -1,7 +1,7 @@ require 'active_support/core_ext/big_decimal/conversions' require 'active_support/number_helper' -class Numeric +module ActiveSupport::NumericWithFormat # Provides options for converting numbers into formatted strings. # Options are provided for phone numbers, currency, percentage, @@ -97,7 +97,10 @@ class Numeric # 1234567.to_s(:human, precision: 1, # separator: ',', # significant: false) # => "1,2 Million" - def to_formatted_s(format = :default, options = {}) + def to_s(*args) + format, options = args + options ||= {} + case format when :phone return ActiveSupport::NumberHelper.number_to_phone(self, options) @@ -114,32 +117,16 @@ class Numeric when :human_size return ActiveSupport::NumberHelper.number_to_human_size(self, options) else - self.to_default_s - end - end - - [Fixnum, Bignum].each do |klass| - klass.class_eval do - alias_method :to_default_s, :to_s - def to_s(base_or_format = 10, options = nil) - if base_or_format.is_a?(Symbol) - to_formatted_s(base_or_format, options || {}) - else - to_default_s(base_or_format) - end - end + super end end - Float.class_eval do - alias_method :to_default_s, :to_s - def to_s(*args) - if args.empty? - to_default_s - else - to_formatted_s(*args) - end - end + def to_formatted_s(*args) + to_s(*args) end + deprecate to_formatted_s: :to_s +end +[Fixnum, Bignum, Float, BigDecimal].each do |klass| + klass.prepend(ActiveSupport::NumericWithFormat) end diff --git a/activesupport/lib/active_support/core_ext/object/deep_dup.rb b/activesupport/lib/active_support/core_ext/object/deep_dup.rb index ad5b2af161..8dfeed0066 100644 --- a/activesupport/lib/active_support/core_ext/object/deep_dup.rb +++ b/activesupport/lib/active_support/core_ext/object/deep_dup.rb @@ -39,9 +39,15 @@ class Hash # hash[:a][:c] # => nil # dup[:a][:c] # => "c" def deep_dup - each_with_object(dup) do |(key, value), hash| - hash.delete(key) - hash[key.deep_dup] = value.deep_dup + hash = dup + each_pair do |key, value| + if key.frozen? && ::String === key + hash[key] = value.deep_dup + else + hash.delete(key) + hash[key.deep_dup] = value.deep_dup + end end + hash end end diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 8b27ec4413..510fa48189 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -37,7 +37,7 @@ class ERB if s.html_safe? s else - s.gsub(HTML_ESCAPE_REGEXP, HTML_ESCAPE) + ActiveSupport::Multibyte::Unicode.tidy_bytes(s).gsub(HTML_ESCAPE_REGEXP, HTML_ESCAPE) end end module_function :unwrapped_html_escape @@ -50,7 +50,7 @@ class ERB # html_escape_once('<< Accept & Checkout') # # => "<< Accept & Checkout" def html_escape_once(s) - result = s.to_s.gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE) + result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE) s.html_safe? ? result.html_safe : result end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index ce2dbfb29d..82e003fc3b 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -18,7 +18,7 @@ class Time # Returns the number of days in the given month. # If no year is specified, it will use the current year. - def days_in_month(month, year = now.year) + def days_in_month(month, year = current.year) if month == 2 && ::Date.gregorian_leap?(year) 29 else @@ -51,9 +51,9 @@ class Time # Returns the number of seconds since 00:00:00. # - # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0 - # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296 - # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399 + # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0.0 + # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0 + # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0 def seconds_since_midnight to_i - change(:hour => 0).to_i + (usec / 1.0e+6) end diff --git a/activesupport/lib/active_support/core_ext/time/conversions.rb b/activesupport/lib/active_support/core_ext/time/conversions.rb index 24d13937f6..536c4bf525 100644 --- a/activesupport/lib/active_support/core_ext/time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/time/conversions.rb @@ -6,6 +6,7 @@ class Time :db => '%Y-%m-%d %H:%M:%S', :number => '%Y%m%d%H%M%S', :nsec => '%Y%m%d%H%M%S%9N', + :usec => '%Y%m%d%H%M%S%6N', :time => '%H:%M', :short => '%d %b %H:%M', :long => '%B %d, %Y %H:%M', @@ -24,7 +25,7 @@ class Time # # This method is aliased to <tt>to_s</tt>. # - # time = Time.now # => Thu Jan 18 06:10:17 CST 2007 + # time = Time.now # => 2007-01-18 06:10:17 -06:00 # # time.to_formatted_s(:time) # => "06:10" # time.to_s(:time) # => "06:10" diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb index c74e9c40ac..32fe8025fe 100644 --- a/activesupport/lib/active_support/deprecation/method_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb @@ -9,37 +9,61 @@ module ActiveSupport # module Fred # extend self # - # def foo; end - # def bar; end - # def baz; end + # def aaa; end + # def bbb; end + # def ccc; end + # def ddd; end + # def eee; end # end # - # ActiveSupport::Deprecation.deprecate_methods(Fred, :foo, bar: :qux, baz: 'use Bar#baz instead') - # # => [:foo, :bar, :baz] + # Using the default deprecator: + # ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead') + # # => [:aaa, :bbb, :ccc] # - # Fred.foo - # # => "DEPRECATION WARNING: foo is deprecated and will be removed from Rails 4.1." + # Fred.aaa + # # DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.0. (called from irb_binding at (irb):10) + # # => nil # - # Fred.bar - # # => "DEPRECATION WARNING: bar is deprecated and will be removed from Rails 4.1 (use qux instead)." + # Fred.bbb + # # DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.0 (use zzz instead). (called from irb_binding at (irb):11) + # # => nil # - # Fred.baz - # # => "DEPRECATION WARNING: baz is deprecated and will be removed from Rails 4.1 (use Bar#baz instead)." + # Fred.ccc + # # DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.0 (use Bar#ccc instead). (called from irb_binding at (irb):12) + # # => nil + # + # Passing in a custom deprecator: + # custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem') + # ActiveSupport::Deprecation.deprecate_methods(Fred, ddd: :zzz, deprecator: custom_deprecator) + # # => [:ddd] + # + # Fred.ddd + # DEPRECATION WARNING: ddd is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):15) + # # => nil + # + # Using a custom deprecator directly: + # custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem') + # custom_deprecator.deprecate_methods(Fred, eee: :zzz) + # # => [:eee] + # + # Fred.eee + # DEPRECATION WARNING: eee is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):18) + # # => nil def deprecate_methods(target_module, *method_names) options = method_names.extract_options! - deprecator = options.delete(:deprecator) || ActiveSupport::Deprecation.instance + deprecator = options.delete(:deprecator) || self method_names += options.keys - method_names.each do |method_name| - mod = Module.new do + mod = Module.new do + method_names.each do |method_name| define_method(method_name) do |*args, &block| deprecator.deprecation_warning(method_name, options[method_name]) super(*args, &block) end end - - target_module.prepend(mod) end + + target_module.prepend(mod) end end end diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb index 0371f760b0..4ff35a45a1 100644 --- a/activesupport/lib/active_support/hash_with_indifferent_access.rb +++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb @@ -59,6 +59,10 @@ module ActiveSupport if constructor.respond_to?(:to_hash) super() update(constructor) + + hash = constructor.to_hash + self.default = hash.default if hash.default + self.default_proc = hash.default_proc if hash.default_proc else super(constructor) end @@ -73,11 +77,12 @@ module ActiveSupport end def self.new_from_hash_copying_default(hash) - hash = hash.to_hash - new(hash).tap do |new_hash| - new_hash.default = hash.default - new_hash.default_proc = hash.default_proc if hash.default_proc - end + ActiveSupport::Deprecation.warn(<<-MSG.squish) + `ActiveSupport::HashWithIndifferentAccess.new_from_hash_copying_default` + has been deprecated, and will be removed in Rails 5.1. The behavior of + this method is now identical to the behavior of `.new`. + MSG + new(hash) end def self.[](*args) @@ -206,7 +211,7 @@ module ActiveSupport # hash['a'] = nil # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1} def reverse_merge(other_hash) - super(self.class.new_from_hash_copying_default(other_hash)) + super(self.class.new(other_hash)) end # Same semantics as +reverse_merge+ but modifies the receiver in-place. @@ -219,7 +224,7 @@ module ActiveSupport # h = { "a" => 100, "b" => 200 } # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400} def replace(other_hash) - super(self.class.new_from_hash_copying_default(other_hash)) + super(self.class.new(other_hash)) end # Removes the specified key from the hash. diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb index 7472d4386a..103207fb63 100644 --- a/activesupport/lib/active_support/inflector/transliterate.rb +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -69,10 +69,12 @@ module ActiveSupport # parameterize("Donald E. Knuth") # => "donald-e-knuth" # parameterize("^trés|Jolie-- ") # => "tres-jolie" def parameterize(string, sep = '-') - # replace accented chars with their ascii equivalents + # Replace accented chars with their ASCII equivalents. parameterized_string = transliterate(string) - # Turn unwanted chars into the separator + + # Turn unwanted chars into the separator. parameterized_string.gsub!(/[^a-z0-9\-_]+/i, sep) + unless sep.nil? || sep.empty? if sep == "-".freeze re_duplicate_separator = /-{2,}/ @@ -87,6 +89,7 @@ module ActiveSupport # Remove leading/trailing separator. parameterized_string.gsub!(re_leading_trailing_separator, ''.freeze) end + parameterized_string.downcase! parameterized_string end diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index f6a2e7e949..707cf200b5 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -86,7 +86,8 @@ module ActiveSupport #:nodoc: end # Works like <tt>String#slice!</tt>, but returns an instance of - # Chars, or nil if the string was not modified. + # Chars, or nil if the string was not modified. The string will not be + # modified if the range given is out of bounds # # string = 'Welcome' # string.mb_chars.slice!(3) # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c"> @@ -94,7 +95,10 @@ module ActiveSupport #:nodoc: # string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo"> # string # => 'me' def slice!(*args) - chars(@wrapped_string.slice!(*args)) + string_sliced = @wrapped_string.slice!(*args) + if string_sliced + chars(string_sliced) + end end # Reverses all characters in the string. diff --git a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb index 5c6fe2df83..7a1f8171c0 100644 --- a/activesupport/lib/active_support/number_helper/number_to_human_converter.rb +++ b/activesupport/lib/active_support/number_helper/number_to_human_converter.rb @@ -20,9 +20,11 @@ module ActiveSupport exponent = calculate_exponent(units) @number = number / (10 ** exponent) + until (rounded_number = NumberToRoundedConverter.convert(number, options)) != NumberToRoundedConverter.convert(1000, options) + @number = number / 1000.0 + exponent += 3 + end unit = determine_unit(units, exponent) - - rounded_number = NumberToRoundedConverter.convert(number, options) format.gsub('%n'.freeze, rounded_number).gsub('%u'.freeze, unit).strip end diff --git a/activesupport/lib/active_support/per_thread_registry.rb b/activesupport/lib/active_support/per_thread_registry.rb index ca2e4d5625..506dd950cb 100644 --- a/activesupport/lib/active_support/per_thread_registry.rb +++ b/activesupport/lib/active_support/per_thread_registry.rb @@ -43,9 +43,9 @@ module ActiveSupport protected def method_missing(name, *args, &block) # :nodoc: # Caches the method definition as a singleton method of the receiver. - define_singleton_method(name) do |*a, &b| - instance.public_send(name, *a, &b) - end + # + # By letting #delegate handle it, we avoid an enclosure that'll capture args. + singleton_class.delegate name, to: :instance send(name, *args, &block) end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index cd0fb51009..845788b669 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -26,7 +26,7 @@ module ActiveSupport unless zone_default raise 'Value assigned to config.time_zone not recognized. ' \ - 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.' + 'Run "rake time:zones:all" for a time zone names list.' end Time.zone_default = zone_default diff --git a/activesupport/lib/active_support/testing/deprecation.rb b/activesupport/lib/active_support/testing/deprecation.rb index 6c94c611b6..5dfa14eeba 100644 --- a/activesupport/lib/active_support/testing/deprecation.rb +++ b/activesupport/lib/active_support/testing/deprecation.rb @@ -3,8 +3,8 @@ require 'active_support/deprecation' module ActiveSupport module Testing module Deprecation #:nodoc: - def assert_deprecated(match = nil, &block) - result, warnings = collect_deprecations(&block) + def assert_deprecated(match = nil, deprecator = nil, &block) + result, warnings = collect_deprecations(deprecator, &block) assert !warnings.empty?, "Expected a deprecation warning within the block but received none" if match match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp) @@ -13,22 +13,23 @@ module ActiveSupport result end - def assert_not_deprecated(&block) - result, deprecations = collect_deprecations(&block) + def assert_not_deprecated(deprecator = nil, &block) + result, deprecations = collect_deprecations(deprecator, &block) assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}" result end - def collect_deprecations - old_behavior = ActiveSupport::Deprecation.behavior + def collect_deprecations(deprecator = nil) + deprecator ||= ActiveSupport::Deprecation + old_behavior = deprecator.behavior deprecations = [] - ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack| + deprecator.behavior = Proc.new do |message, callstack| deprecations << message end result = yield [result, deprecations] ensure - ActiveSupport::Deprecation.behavior = old_behavior + deprecator.behavior = old_behavior end end end diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index 3592dcba39..79cc748cf5 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -102,7 +102,7 @@ module ActiveSupport # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' # Time.zone.now.utc? # => false def utc? - time_zone.name == 'UTC' + period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT end alias_method :gmt?, :utc? @@ -284,8 +284,8 @@ module ActiveSupport # the current object's time and the +other+ time. # # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' - # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EST -05:00 - # now - 1000 # => Sun, 02 Nov 2014 01:09:48 EST -05:00 + # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00 + # now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00 # # If subtracting a Duration of variable length (i.e., years, months, days), # move backward from #time, otherwise move backward from #utc, for accuracy @@ -294,8 +294,8 @@ module ActiveSupport # For instance, a time - 24.hours will go subtract exactly 24 hours, while a # time - 1.day will subtract 23-25 hours, depending on the day. # - # now - 24.hours # => Sat, 01 Nov 2014 02:26:28 EDT -04:00 - # now - 1.day # => Sat, 01 Nov 2014 01:26:28 EDT -04:00 + # now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 + # now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00 def -(other) if other.acts_like?(:time) to_time - other.to_time @@ -307,10 +307,48 @@ module ActiveSupport end end + # Subtracts an interval of time from the current object's time and returns + # the result as a new TimeWithZone object. + # + # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' + # now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00 + # now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00 + # + # If we're subtracting a Duration of variable length (i.e., years, months, + # days), move backward from #time, otherwise move backward from #utc, for + # accuracy when moving across DST boundaries. + # + # For instance, <tt>time.ago(24.hours)</tt> will move back exactly 24 hours, + # while <tt>time.ago(1.day)</tt> will move back 23-25 hours, depending on + # the day. + # + # now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 + # now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00 def ago(other) since(-other) end + # Uses Date to provide precise Time calculations for years, months, and days + # according to the proleptic Gregorian calendar. The result is returned as a + # new TimeWithZone object. + # + # The +options+ parameter takes a hash with any of these keys: + # <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, + # <tt>:hours</tt>, <tt>:minutes</tt>, <tt>:seconds</tt>. + # + # If advancing by a value of variable length (i.e., years, weeks, months, + # days), move forward from #time, otherwise move forward from #utc, for + # accuracy when moving across DST boundaries. + # + # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' + # now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 + # now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00 + # now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00 + # now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00 + # now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00 + # now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00 + # now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00 + # now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00 def advance(options) # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time, # otherwise advance from #utc, for accuracy when moving across DST boundaries diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 681f659100..9f4bb6762d 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -26,12 +26,6 @@ module ActiveSupport # Time.zone # => #<ActiveSupport::TimeZone:0x514834...> # Time.zone.name # => "Eastern Time (US & Canada)" # Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00 - # - # The version of TZInfo bundled with Active Support only includes the - # definitions necessary to support the zones defined by the TimeZone class. - # If you need to use zones that aren't defined by TimeZone, you'll need to - # install the TZInfo gem (if a recent version of the gem is installed locally, - # this will be used instead of the bundled version.) class TimeZone # Keys are Rails TimeZone names, values are TZInfo identifiers. MAPPING = { |