diff options
Diffstat (limited to 'activesupport/lib/active_support')
26 files changed, 130 insertions, 148 deletions
diff --git a/activesupport/lib/active_support/all.rb b/activesupport/lib/active_support/all.rb index def8eca89f..f537818300 100644 --- a/activesupport/lib/active_support/all.rb +++ b/activesupport/lib/active_support/all.rb @@ -1,4 +1,3 @@ require 'active_support' require 'active_support/time' require 'active_support/core_ext' -require 'active_support/json' diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index c4e1eb2c04..1c7802f7de 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -432,7 +432,7 @@ module ActiveSupport options = filters.last.is_a?(Hash) ? filters.pop : {} filters.unshift(block) if block - ([self] + self.descendants).each do |target| + ([self] + ActiveSupport::DescendantsTracker.descendants(self)).each do |target| chain = target.send("_#{name}_callbacks") yield chain, type, filters, options target.__define_runner(name) @@ -506,7 +506,7 @@ module ActiveSupport def reset_callbacks(symbol) callbacks = send("_#{symbol}_callbacks") - self.descendants.each do |target| + ActiveSupport::DescendantsTracker.descendants(self).each do |target| chain = target.send("_#{symbol}_callbacks") callbacks.each { |c| chain.delete(c) } target.__define_runner(symbol) diff --git a/activesupport/lib/active_support/core_ext/class/subclasses.rb b/activesupport/lib/active_support/core_ext/class/subclasses.rb index 7d58a8b56a..3e5d1a2a42 100644 --- a/activesupport/lib/active_support/core_ext/class/subclasses.rb +++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb @@ -2,54 +2,49 @@ require 'active_support/core_ext/module/anonymous' require 'active_support/core_ext/module/reachable' class Class #:nodoc: - # Returns an array with the names of the subclasses of +self+ as strings. - # - # Integer.subclasses # => ["Bignum", "Fixnum"] - def subclasses - Class.subclasses_of(self).map { |o| o.to_s } - end - # Rubinius if defined?(Class.__subclasses__) + alias :subclasses :__subclasses__ + def descendants - subclasses = [] - __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendants } - subclasses + descendants = [] + __subclasses__.each do |k| + descendants << k + descendants.concat k.descendants + end + descendants end - else - # MRI + else # MRI begin ObjectSpace.each_object(Class.new) {} def descendants - subclasses = [] + descendants = [] ObjectSpace.each_object(class << self; self; end) do |k| - subclasses << k unless k == self + descendants.unshift k unless k == self end - subclasses + descendants end - # JRuby - rescue StandardError + rescue StandardError # JRuby def descendants - subclasses = [] + descendants = [] ObjectSpace.each_object(Class) do |k| - subclasses << k if k < self + descendants.unshift k if k < self end - subclasses.uniq! - subclasses + descendants.uniq! + descendants end end - end - # Exclude this class unless it's a subclass of our supers and is defined. - # We check defined? in case we find a removed class that has yet to be - # garbage collected. This also fails for anonymous classes -- please - # submit a patch if you have a workaround. - def self.subclasses_of(*superclasses) #:nodoc: - subclasses = [] - superclasses.each do |klass| - subclasses.concat klass.descendants.select {|k| k.anonymous? || k.reachable?} + # Returns an array with the direct children of +self+. + # + # Integer.subclasses # => [Bignum, Fixnum] + def subclasses + subclasses, chain = [], descendants + chain.each do |k| + subclasses << k unless chain.any? { |c| c > k } + end + subclasses end - subclasses end end diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 28fec5394f..e6a213625c 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -1,7 +1,8 @@ require 'date' require 'active_support/duration' -require 'active_support/core_ext/time/zones' require 'active_support/core_ext/object/acts_like' +require 'active_support/core_ext/date/zones' +require 'active_support/core_ext/time/zones' class Date if RUBY_VERSION < '1.9' diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb index ba17b0a06b..092f936961 100644 --- a/activesupport/lib/active_support/core_ext/date/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date/conversions.rb @@ -1,6 +1,6 @@ require 'date' require 'active_support/inflector' -require 'active_support/core_ext/time/calculations' +require 'active_support/core_ext/date/zones' class Date DATE_FORMATS = { @@ -13,10 +13,10 @@ class Date } # Ruby 1.9 has Date#to_time which converts to localtime only. - remove_method :to_time if instance_methods.include?(:to_time) + remove_method :to_time if method_defined?(:to_time) # Ruby 1.9 has Date#xmlschema which converts to a string without the time component. - remove_method :xmlschema if instance_methods.include?(:xmlschema) + remove_method :xmlschema if method_defined?(:xmlschema) # Convert to a formatted string. See DATE_FORMATS for predefined formats. # @@ -81,16 +81,6 @@ class Date def to_time(form = :local) ::Time.send("#{form}_time", year, month, day) end - - # Converts Date to a TimeWithZone in the current zone if Time.zone_default is set, - # otherwise converts Date to a Time via Date#to_time - def to_time_in_current_zone - if ::Time.zone_default - ::Time.zone.local(year, month, day) - else - to_time - end - end # Converts a Date instance to a DateTime, where the time is set to the beginning of the day # and UTC offset is set to 0. diff --git a/activesupport/lib/active_support/core_ext/date/zones.rb b/activesupport/lib/active_support/core_ext/date/zones.rb new file mode 100644 index 0000000000..3a83af6be2 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/date/zones.rb @@ -0,0 +1,14 @@ +require 'date' +require 'active_support/core_ext/time/zones' + +class Date + # Converts Date to a TimeWithZone in the current zone if Time.zone_default is set, + # otherwise converts Date to a Time via Date#to_time + def to_time_in_current_zone + if ::Time.zone_default + ::Time.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 26979aa906..1dc3933e12 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -1,5 +1,6 @@ require 'rational' unless RUBY_VERSION >= '1.9.2' require 'active_support/core_ext/object/acts_like' +require 'active_support/core_ext/time/zones' class DateTime class << self diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index c3f0acce25..47b8aa59fb 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -1,6 +1,7 @@ require 'active_support/inflector' require 'active_support/core_ext/time/conversions' require 'active_support/core_ext/date_time/calculations' +require 'active_support/values/time_zone' class DateTime # Ruby 1.9 has DateTime#to_time which internally relies on Time. We define our own #to_time which allows diff --git a/activesupport/lib/active_support/core_ext/date_time/zones.rb b/activesupport/lib/active_support/core_ext/date_time/zones.rb index 6002d4ad2a..a7411d54ae 100644 --- a/activesupport/lib/active_support/core_ext/date_time/zones.rb +++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/time/zones' + class DateTime # Returns the simultaneous time in <tt>Time.zone</tt>. # diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb index d023b4bcff..a1c351bfd9 100644 --- a/activesupport/lib/active_support/core_ext/logger.rb +++ b/activesupport/lib/active_support/core_ext/logger.rb @@ -18,7 +18,7 @@ end require 'logger' -# Extensions to the built in Ruby logger. +# Extensions to the built-in Ruby logger. # # If you want to use the default log formatter as defined in the Ruby core, then you # will need to set the formatter for the logger as in: diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb index 3a6100f776..27618b55c6 100644 --- a/activesupport/lib/active_support/core_ext/object.rb +++ b/activesupport/lib/active_support/core_ext/object.rb @@ -6,9 +6,9 @@ require 'active_support/core_ext/object/try' require 'active_support/core_ext/object/conversions' require 'active_support/core_ext/object/instance_variables' require 'active_support/core_ext/object/misc' -require 'active_support/core_ext/object/extending' require 'active_support/core_ext/object/returning' +require 'active_support/core_ext/object/to_json' require 'active_support/core_ext/object/to_param' require 'active_support/core_ext/object/to_query' require 'active_support/core_ext/object/with_options' diff --git a/activesupport/lib/active_support/core_ext/object/extending.rb b/activesupport/lib/active_support/core_ext/object/extending.rb deleted file mode 100644 index c4c37b6a2a..0000000000 --- a/activesupport/lib/active_support/core_ext/object/extending.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'active_support/core_ext/class/subclasses' - -class Object - # Exclude this class unless it's a subclass of our supers and is defined. - # We check defined? in case we find a removed class that has yet to be - # garbage collected. This also fails for anonymous classes -- please - # submit a patch if you have a workaround. - def subclasses_of(*superclasses) #:nodoc: - Class.subclasses_of(*superclasses) - end -end diff --git a/activesupport/lib/active_support/core_ext/object/to_json.rb b/activesupport/lib/active_support/core_ext/object/to_json.rb new file mode 100644 index 0000000000..14ef27340e --- /dev/null +++ b/activesupport/lib/active_support/core_ext/object/to_json.rb @@ -0,0 +1,19 @@ +# Hack to load json gem first so we can overwrite its to_json. +begin + require 'json' +rescue LoadError +end + +# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting +# their default behavior. That said, we need to define the basic to_json method in all of them, +# otherwise they will always use to_json gem implementation, which is backwards incompatible in +# several cases (for instance, the JSON implementation for Hash does not work) with inheritance +# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json. +[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass| + klass.class_eval <<-RUBY, __FILE__, __LINE__ + # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. + def to_json(options = nil) + ActiveSupport::JSON.encode(self, options) + end + RUBY +end diff --git a/activesupport/lib/active_support/core_ext/string/multibyte.rb b/activesupport/lib/active_support/core_ext/string/multibyte.rb index 3dfe996d06..16ccd36458 100644 --- a/activesupport/lib/active_support/core_ext/string/multibyte.rb +++ b/activesupport/lib/active_support/core_ext/string/multibyte.rb @@ -2,7 +2,7 @@ require 'active_support/multibyte' class String - if '1.9'.respond_to?(:force_encoding) + if RUBY_VERSION >= "1.9" # == Multibyte proxy # # +mb_chars+ is a multibyte safe proxy for string methods. diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 3c218d88e5..90b6cd3685 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -40,6 +40,11 @@ class Time def local_time(*args) time_with_datetime_fallback(:local, *args) end + + # Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>. + def current + ::Time.zone_default ? ::Time.zone.now : ::Time.now + end end # Tells whether the Time object's time lies in the past diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb index a02402aa3f..6b9ee84d5c 100644 --- a/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/activesupport/lib/active_support/core_ext/time/zones.rb @@ -41,11 +41,6 @@ class Time ::Time.zone = old_zone end - # Returns <tt>Time.zone.now</tt> when <tt>config.time_zone</tt> is set, otherwise just returns <tt>Time.now</tt>. - def current - ::Time.zone_default ? ::Time.zone.now : ::Time.now - end - private def get_zone(time_zone) return time_zone if time_zone.nil? || time_zone.is_a?(ActiveSupport::TimeZone) diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index feb1508586..f54f65dcf0 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -1,4 +1,5 @@ require "active_support/notifications" +require "active_support/core_ext/array/wrap" module ActiveSupport module Deprecation @@ -7,11 +8,11 @@ module ActiveSupport attr_accessor :debug def behavior - @behavior ||= DEFAULT_BEHAVIORS[:stderr] + @behavior ||= [DEFAULT_BEHAVIORS[:stderr]] end def behavior=(behavior) - @behavior = DEFAULT_BEHAVIORS[behavior] || behavior + @behavior = Array.wrap(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b } end end diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb index 03c445ffbf..49d58cd3a1 100644 --- a/activesupport/lib/active_support/deprecation/reporting.rb +++ b/activesupport/lib/active_support/deprecation/reporting.rb @@ -4,8 +4,9 @@ module ActiveSupport attr_accessor :silenced def warn(message = nil, callstack = caller) - if behavior && !silenced - behavior.call(deprecation_message(callstack, message), callstack) + return if silenced + deprecation_message(callstack, message).tap do |m| + behavior.each { |b| b.call(m, callstack) } end end diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb index a587d7770c..6cba84d79e 100644 --- a/activesupport/lib/active_support/descendants_tracker.rb +++ b/activesupport/lib/active_support/descendants_tracker.rb @@ -4,16 +4,23 @@ module ActiveSupport # This module provides an internal implementation to track descendants # which is faster than iterating through ObjectSpace. module DescendantsTracker - @@descendants = Hash.new { |h, k| h[k] = [] } + @@direct_descendants = Hash.new { |h, k| h[k] = [] } - def self.descendants - @@descendants + def self.direct_descendants(klass) + @@direct_descendants[klass] + end + + def self.descendants(klass) + @@direct_descendants[klass].inject([]) do |descendants, klass| + descendants << klass + descendants.concat klass.descendants + end end def self.clear - @@descendants.each do |klass, descendants| + @@direct_descendants.each do |klass, descendants| if ActiveSupport::Dependencies.autoloaded?(klass) - @@descendants.delete(klass) + @@direct_descendants.delete(klass) else descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) } end @@ -26,14 +33,11 @@ module ActiveSupport end def direct_descendants - @@descendants[self] + DescendantsTracker.direct_descendants(self) end def descendants - @@descendants[self].inject([]) do |descendants, klass| - descendants << klass - descendants.concat klass.descendants - end + DescendantsTracker.descendants(self) end end end
\ No newline at end of file diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index 5f5b264eb9..cd658fe173 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,16 +1,15 @@ module ActiveSupport # This class is responsible to track files and invoke the given block # whenever one of these files are changed. For example, this class - # is used by Rails to reload routes whenever they are changed upon - # a new request. + # is used by Rails to reload the I18n framework whenever they are + # changed upon a new request. # - # routes_reloader = ActiveSupport::FileUpdateChecker.new(paths) do - # paths.each { |p| load(p) } - # Rails::Application.routes.reload! + # i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do + # I18n.reload! # end # # ActionDispatch::Callbacks.to_prepare do - # routes_reloader.execute_if_updated + # i18n_reloader.execute_if_updated # end # class FileUpdateChecker diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb index d82e54f1d4..db09919fd3 100644 --- a/activesupport/lib/active_support/i18n_railtie.rb +++ b/activesupport/lib/active_support/i18n_railtie.rb @@ -1,6 +1,7 @@ require "active_support" require "rails" require "active_support/file_update_checker" +require "active_support/core_ext/array/wrap" module I18n class Railtie < Rails::Railtie diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb index dd94315111..2f9588e0f4 100644 --- a/activesupport/lib/active_support/json/encoding.rb +++ b/activesupport/lib/active_support/json/encoding.rb @@ -1,20 +1,18 @@ -# encoding: utf-8 +require 'active_support/core_ext/object/to_json' +require 'active_support/core_ext/module/delegation' +require 'active_support/deprecation' +require 'active_support/json/variable' + require 'bigdecimal' -require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/big_decimal/conversions' # for #to_s +require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/slice' -require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/object/instance_variables' -require 'active_support/deprecation' - -require 'active_support/time' - -# Hack to load json gem first so we can overwrite its to_json. -begin - require 'json' -rescue LoadError -end +require 'time' +require 'active_support/core_ext/time/conversions' +require 'active_support/core_ext/date_time/conversions' +require 'active_support/core_ext/date/conversions' module ActiveSupport class << self @@ -128,20 +126,6 @@ module ActiveSupport end end -# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting -# their default behavior. That said, we need to define the basic to_json method in all of them, -# otherwise they will always use to_json gem implementation, which is backwards incompatible in -# several cases (for instance, the JSON implementation for Hash does not work) with inheritance -# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json. -[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass| - klass.class_eval <<-RUBY, __FILE__, __LINE__ - # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info. - def to_json(options = nil) - ActiveSupport::JSON.encode(self, options) - end - RUBY -end - class Object def as_json(options = nil) #:nodoc: if respond_to?(:to_hash) @@ -152,12 +136,6 @@ class Object end end -# A string that returns itself as its JSON-encoded form. -class ActiveSupport::JSON::Variable < String - def as_json(options = nil) self end #:nodoc: - def encode_json(encoder) self end #:nodoc: -end - class TrueClass AS_JSON = ActiveSupport::JSON::Variable.new('true').freeze def as_json(options = nil) AS_JSON end #:nodoc: diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb index daa7449b71..5685ed18b7 100644 --- a/activesupport/lib/active_support/json/variable.rb +++ b/activesupport/lib/active_support/json/variable.rb @@ -2,10 +2,8 @@ module ActiveSupport module JSON # A string that returns itself as its JSON-encoded form. class Variable < String - private - def rails_to_json(*) - self - end + def as_json(options = nil) self end #:nodoc: + def encode_json(encoder) self end #:nodoc: end end end diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb index 8823e4a5ed..51c2a0edac 100644 --- a/activesupport/lib/active_support/multibyte/chars.rb +++ b/activesupport/lib/active_support/multibyte/chars.rb @@ -325,18 +325,6 @@ module ActiveSupport #:nodoc: end alias_method :[], :slice - # Like <tt>String#slice!</tt>, except instead of byte offsets you specify character offsets. - # - # Example: - # s = 'こんにちは' - # s.mb_chars.slice!(2..3).to_s #=> "にち" - # s #=> "こんは" - def slice!(*args) - slice = self[*args] - self[*args] = '' - slice - end - # Limit the byte size of the string to a number of bytes without breaking characters. Usable # when the storage for a string is limited for some reason. # @@ -425,14 +413,14 @@ module ActiveSupport #:nodoc: chars(Unicode.tidy_bytes(@wrapped_string, force)) end - %w(lstrip rstrip strip reverse upcase downcase tidy_bytes capitalize).each do |method| - define_method("#{method}!") do |*args| - unless args.nil? - @wrapped_string = send(method, *args).to_s - else - @wrapped_string = send(method).to_s + %w(capitalize downcase lstrip reverse rstrip slice strip tidy_bytes upcase).each do |method| + # Only define a corresponding bang method for methods defined in the proxy; On 1.9 the proxy will + # exclude lstrip!, rstrip! and strip! because they are already work as expected on multibyte strings. + if public_method_defined?(method) + define_method("#{method}!") do |*args| + @wrapped_string = send(args.nil? ? method : method, *args).to_s + self end - self end end diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb index 784c7173a9..86f057d676 100644 --- a/activesupport/lib/active_support/time.rb +++ b/activesupport/lib/active_support/time.rb @@ -24,6 +24,7 @@ require 'active_support/core_ext/date/acts_like' require 'active_support/core_ext/date/freeze' 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' diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 05b40298d3..49dd8a1b99 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -1,11 +1,5 @@ require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' -begin - require 'tzinfo' -rescue LoadError => e - $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" - raise e -end # The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following: # @@ -201,6 +195,12 @@ module ActiveSupport # (GMT). Seconds were chosen as the offset unit because that is the unit that # Ruby uses to represent time zone offsets (see Time#utc_offset). def initialize(name, utc_offset = nil, tzinfo = nil) + begin + require 'tzinfo' + rescue LoadError => e + $stderr.puts "You don't have tzinfo installed in your application. Please add it to your Gemfile and run bundle install" + raise e + end @name = name @utc_offset = utc_offset @tzinfo = tzinfo || TimeZone.find_tzinfo(name) |