aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib')
-rw-r--r--activesupport/lib/active_support.rb3
-rw-r--r--activesupport/lib/active_support/callbacks.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/class/subclasses.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/zones.rb2
-rw-r--r--[-rwxr-xr-x]activesupport/lib/active_support/core_ext/object/to_param.rb0
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb2
-rw-r--r--activesupport/lib/active_support/descendants_tracker.rb39
-rw-r--r--activesupport/lib/active_support/file_update_checker.rb37
-rw-r--r--activesupport/lib/active_support/i18n.rb1
-rw-r--r--activesupport/lib/active_support/i18n_railtie.rb80
-rw-r--r--activesupport/lib/active_support/json/backends/yajl.rb2
-rw-r--r--activesupport/lib/active_support/multibyte/chars.rb34
-rw-r--r--activesupport/lib/active_support/railtie.rb72
-rw-r--r--activesupport/lib/active_support/testing/performance.rb122
14 files changed, 251 insertions, 163 deletions
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index e34e46b4cf..3ce5476bbd 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -39,6 +39,9 @@ require "active_support/dependencies/autoload"
module ActiveSupport
extend ActiveSupport::Autoload
+ autoload :DescendantsTracker
+ autoload :FileUpdateChecker
+
# TODO: Narrow this list down
eager_autoload do
autoload :BacktraceCleaner
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 3ff33eea72..c4e1eb2c04 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -1,6 +1,6 @@
+require 'active_support/descendants_tracker'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/class/inheritable_attributes'
-require 'active_support/core_ext/class/subclasses'
require 'active_support/core_ext/kernel/reporting'
require 'active_support/core_ext/kernel/singleton_class'
@@ -85,6 +85,10 @@ module ActiveSupport
module Callbacks
extend Concern
+ included do
+ extend ActiveSupport::DescendantsTracker
+ end
+
def run_callbacks(kind, *args, &block)
send("_run_#{kind}_callbacks", *args, &block)
end
@@ -428,7 +432,7 @@ module ActiveSupport
options = filters.last.is_a?(Hash) ? filters.pop : {}
filters.unshift(block) if block
- ([self] + self.descendents).each do |target|
+ ([self] + self.descendants).each do |target|
chain = target.send("_#{name}_callbacks")
yield chain, type, filters, options
target.__define_runner(name)
@@ -502,7 +506,7 @@ module ActiveSupport
def reset_callbacks(symbol)
callbacks = send("_#{symbol}_callbacks")
- self.descendents.each do |target|
+ self.descendants.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 bbd8f5aef6..7d58a8b56a 100644
--- a/activesupport/lib/active_support/core_ext/class/subclasses.rb
+++ b/activesupport/lib/active_support/core_ext/class/subclasses.rb
@@ -11,9 +11,9 @@ class Class #:nodoc:
# Rubinius
if defined?(Class.__subclasses__)
- def descendents
+ def descendants
subclasses = []
- __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendents }
+ __subclasses__.each {|k| subclasses << k; subclasses.concat k.descendants }
subclasses
end
else
@@ -21,7 +21,7 @@ class Class #:nodoc:
begin
ObjectSpace.each_object(Class.new) {}
- def descendents
+ def descendants
subclasses = []
ObjectSpace.each_object(class << self; self; end) do |k|
subclasses << k unless k == self
@@ -30,7 +30,7 @@ class Class #:nodoc:
end
# JRuby
rescue StandardError
- def descendents
+ def descendants
subclasses = []
ObjectSpace.each_object(Class) do |k|
subclasses << k if k < self
@@ -48,7 +48,7 @@ class Class #:nodoc:
def self.subclasses_of(*superclasses) #:nodoc:
subclasses = []
superclasses.each do |klass|
- subclasses.concat klass.descendents.select {|k| k.anonymous? || k.reachable?}
+ subclasses.concat klass.descendants.select {|k| k.anonymous? || k.reachable?}
end
subclasses
end
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 98565e6750..6002d4ad2a 100644
--- a/activesupport/lib/active_support/core_ext/date_time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/zones.rb
@@ -12,6 +12,8 @@ class DateTime
#
# DateTime.new(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
def in_time_zone(zone = ::Time.zone)
+ return self unless zone
+
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
end
end
diff --git a/activesupport/lib/active_support/core_ext/object/to_param.rb b/activesupport/lib/active_support/core_ext/object/to_param.rb
index 06f077e920..06f077e920 100755..100644
--- a/activesupport/lib/active_support/core_ext/object/to_param.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_param.rb
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index adc9fe3824..a02402aa3f 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -73,6 +73,8 @@ class Time
#
# Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
def in_time_zone(zone = ::Time.zone)
+ return self unless zone
+
ActiveSupport::TimeWithZone.new(utc? ? self : getutc, ::Time.__send__(:get_zone, zone))
end
end
diff --git a/activesupport/lib/active_support/descendants_tracker.rb b/activesupport/lib/active_support/descendants_tracker.rb
new file mode 100644
index 0000000000..a587d7770c
--- /dev/null
+++ b/activesupport/lib/active_support/descendants_tracker.rb
@@ -0,0 +1,39 @@
+require 'active_support/dependencies'
+
+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] = [] }
+
+ def self.descendants
+ @@descendants
+ end
+
+ def self.clear
+ @@descendants.each do |klass, descendants|
+ if ActiveSupport::Dependencies.autoloaded?(klass)
+ @@descendants.delete(klass)
+ else
+ descendants.reject! { |v| ActiveSupport::Dependencies.autoloaded?(v) }
+ end
+ end
+ end
+
+ def inherited(base)
+ self.direct_descendants << base
+ super
+ end
+
+ def direct_descendants
+ @@descendants[self]
+ end
+
+ def descendants
+ @@descendants[self].inject([]) do |descendants, klass|
+ descendants << klass
+ descendants.concat klass.descendants
+ end
+ 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
new file mode 100644
index 0000000000..c0b5ca4deb
--- /dev/null
+++ b/activesupport/lib/active_support/file_update_checker.rb
@@ -0,0 +1,37 @@
+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.
+ #
+ # routes_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
+ # paths.each { |p| load(p) }
+ # Rails::Application.routes.reload!
+ # end
+ #
+ # ActionDispatch::Callbacks.to_prepare do
+ # routes_reloader.execute_if_updated
+ # end
+ #
+ class FileUpdateChecker
+ attr_reader :paths, :last_update_at
+
+ def initialize(paths, calculate=false, &block)
+ @paths = paths
+ @block = block
+ @last_update_at = updated_at if calculate
+ end
+
+ def updated_at
+ paths.map { |path| File.stat(path).mtime }.max
+ end
+
+ def execute_if_updated
+ current_update_at = self.updated_at
+ if @last_update_at != current_update_at
+ @last_update_at = current_update_at
+ @block.call
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/i18n.rb b/activesupport/lib/active_support/i18n.rb
index 0ffdd904fd..45b9d20c01 100644
--- a/activesupport/lib/active_support/i18n.rb
+++ b/activesupport/lib/active_support/i18n.rb
@@ -4,5 +4,6 @@ rescue LoadError => e
$stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
raise e
end
+
I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
ActiveSupport.run_load_hooks(:i18n)
diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb
new file mode 100644
index 0000000000..d82e54f1d4
--- /dev/null
+++ b/activesupport/lib/active_support/i18n_railtie.rb
@@ -0,0 +1,80 @@
+require "active_support"
+require "rails"
+require "active_support/file_update_checker"
+
+module I18n
+ class Railtie < Rails::Railtie
+ config.i18n = ActiveSupport::OrderedOptions.new
+ config.i18n.railties_load_path = []
+ config.i18n.load_path = []
+ config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
+
+ def self.reloader
+ @reloader ||= ActiveSupport::FileUpdateChecker.new([]){ I18n.reload! }
+ end
+
+ # Add I18n::Railtie.reloader to ActionDispatch callbacks. Since, at this
+ # point, no path was added to the reloader, I18n.reload! is not triggered
+ # on to_prepare callbacks. This will only happen on the config.after_initialize
+ # callback below.
+ initializer "i18n.callbacks" do
+ ActionDispatch::Callbacks.to_prepare do
+ I18n::Railtie.reloader.execute_if_updated
+ end
+ end
+
+ # Set the i18n configuration only after initialization since a lot of
+ # configuration is still usually done in application initializers.
+ config.after_initialize do |app|
+ fallbacks = app.config.i18n.delete(:fallbacks)
+
+ app.config.i18n.each do |setting, value|
+ case setting
+ when :railties_load_path
+ app.config.i18n.load_path.unshift(*value)
+ when :load_path
+ I18n.load_path += value
+ else
+ I18n.send("#{setting}=", value)
+ end
+ end
+
+ init_fallbacks(fallbacks) if fallbacks && validate_fallbacks(fallbacks)
+
+ reloader.paths.concat I18n.load_path
+ reloader.execute_if_updated
+ end
+
+ protected
+
+ def self.include_fallbacks_module
+ I18n.backend.class.send(:include, I18n::Backend::Fallbacks)
+ end
+
+ def self.init_fallbacks(fallbacks)
+ include_fallbacks_module
+
+ args = case fallbacks
+ when ActiveSupport::OrderedOptions
+ [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
+ when Hash, Array
+ Array.wrap(fallbacks)
+ else # TrueClass
+ []
+ end
+
+ I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
+ end
+
+ def self.validate_fallbacks(fallbacks)
+ case fallbacks
+ when ActiveSupport::OrderedOptions
+ !fallbacks.empty?
+ when TrueClass, Array, Hash
+ true
+ else
+ raise "Unexpected fallback type #{fallbacks.inspect}"
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/json/backends/yajl.rb b/activesupport/lib/active_support/json/backends/yajl.rb
index d76f8b03e4..64e50e0d87 100644
--- a/activesupport/lib/active_support/json/backends/yajl.rb
+++ b/activesupport/lib/active_support/json/backends/yajl.rb
@@ -1,4 +1,4 @@
-require 'yajl-ruby' unless defined?(Yajl)
+require 'yajl' unless defined?(Yajl)
module ActiveSupport
module JSON
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index d6ccb4bac1..04193bfa65 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -50,10 +50,6 @@ module ActiveSupport #:nodoc:
end
end
- def <=>(other)
- @wrapped_string <=> other
- end
-
# Forward all undefined methods to the wrapped string.
def method_missing(method, *args, &block)
if method.to_s =~ /!$/
@@ -87,6 +83,16 @@ module ActiveSupport #:nodoc:
include Comparable
+ # Returns <tt>-1</tt>, <tt>0</tt> or <tt>+1</tt> depending on whether the Chars object is to be sorted before,
+ # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+.
+ # See <tt>String#<=></tt> for more details.
+ #
+ # Example:
+ # 'é'.mb_chars <=> 'ü'.mb_chars #=> -1
+ def <=>(other)
+ @wrapped_string <=> other.to_s
+ end
+
if RUBY_VERSION < "1.9"
# Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
# +false+ otherwise.
@@ -94,16 +100,6 @@ module ActiveSupport #:nodoc:
$KCODE == 'UTF8' && consumes?(string)
end
- # Returns <tt>-1</tt>, <tt>0</tt> or <tt>+1</tt> depending on whether the Chars object is to be sorted before,
- # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+.
- # See <tt>String#<=></tt> for more details.
- #
- # Example:
- # 'é'.mb_chars <=> 'ü'.mb_chars #=> -1
- def <=>(other)
- @wrapped_string <=> other.to_s
- end
-
# Returns a new Chars object containing the _other_ object concatenated to the string.
#
# Example:
@@ -375,6 +371,16 @@ module ActiveSupport #:nodoc:
(slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
end
+ # Capitalizes the first letter of every word, when possible.
+ #
+ # Example:
+ # "ÉL QUE SE ENTERÓ".mb_chars.titleize # => "Él Que Se Enteró"
+ # "日本語".mb_chars.titleize # => "日本語"
+ def titleize
+ chars(downcase.to_s.gsub(/\b('?[\S])/u) { Unicode.apply_mapping $1, :uppercase_mapping })
+ end
+ alias_method :titlecase, :titleize
+
# Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
# passing strings to databases and validations.
#
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index 59f9ab18b1..1f32f8718f 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -1,5 +1,6 @@
require "active_support"
require "rails"
+require "active_support/i18n_railtie"
module ActiveSupport
class Railtie < Rails::Railtie
@@ -26,75 +27,4 @@ module ActiveSupport
Time.zone_default = zone_default
end
end
-end
-
-module I18n
- class Railtie < Rails::Railtie
- config.i18n = ActiveSupport::OrderedOptions.new
- config.i18n.railties_load_path = []
- config.i18n.load_path = []
- config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
-
- initializer "i18n.initialize" do
- ActiveSupport.on_load(:i18n) do
- I18n.reload!
-
- ActionDispatch::Callbacks.to_prepare do
- I18n.reload!
- end
- end
- end
-
- # Set the i18n configuration from config.i18n but special-case for
- # the load_path which should be appended to what's already set instead of overwritten.
- config.after_initialize do |app|
- fallbacks = app.config.i18n.delete(:fallbacks)
-
- app.config.i18n.each do |setting, value|
- case setting
- when :railties_load_path
- app.config.i18n.load_path.unshift(*value)
- when :load_path
- I18n.load_path += value
- else
- I18n.send("#{setting}=", value)
- end
- end
-
- init_fallbacks(fallbacks) if fallbacks && validate_fallbacks(fallbacks)
- I18n.reload!
- end
-
- class << self
- protected
-
- def init_fallbacks(fallbacks)
- include_fallbacks_module
- args = case fallbacks
- when ActiveSupport::OrderedOptions
- [*(fallbacks[:defaults] || []) << fallbacks[:map]].compact
- when Hash, Array
- Array.wrap(fallbacks)
- else # TrueClass
- []
- end
- I18n.fallbacks = I18n::Locale::Fallbacks.new(*args)
- end
-
- def include_fallbacks_module
- I18n.backend.class.send(:include, I18n::Backend::Fallbacks)
- end
-
- def validate_fallbacks(fallbacks)
- case fallbacks
- when ActiveSupport::OrderedOptions
- !fallbacks.empty?
- when TrueClass, Array, Hash
- true
- else
- raise "Unexpected fallback type #{fallbacks.inspect}"
- end
- end
- end
- end
end \ No newline at end of file
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index 24eea1e40b..cd628a956d 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -260,14 +260,8 @@ begin
end
protected
- if GC.respond_to?(:enable_stats)
- def with_gc_stats
- GC.enable_stats
- yield
- ensure
- GC.disable_stats
- end
- elsif defined?(GC::Profiler)
+ # Ruby 1.9 + extented GC profiler patch
+ if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data)
def with_gc_stats
GC.start
GC.disable
@@ -277,6 +271,16 @@ begin
GC::Profiler.disable
GC.enable
end
+
+ # Ruby 1.8 + ruby-prof wrapper (enable/disable stats for Benchmarker)
+ elsif GC.respond_to?(:enable_stats)
+ def with_gc_stats
+ GC.enable_stats
+ yield
+ ensure
+ GC.disable_stats
+ end
+
else
def with_gc_stats
yield
@@ -319,7 +323,7 @@ begin
def initialize(*args)
# FIXME: yeah my CPU is 2.33 GHz
- RubyProf.cpu_frequency = 2.33e9
+ RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
super
end
@@ -331,38 +335,8 @@ begin
class Memory < Base
Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
- # ruby-prof wrapper
- if RubyProf.respond_to?(:measure_memory)
- def measure
- RubyProf.measure_memory / 1024.0
- end
-
- # Ruby 1.8 + railsbench patch
- elsif GC.respond_to?(:allocated_size)
- def measure
- GC.allocated_size / 1024.0
- end
-
- # Ruby 1.8 + lloyd patch
- elsif GC.respond_to?(:heap_info)
- def measure
- GC.heap_info['heap_current_memory'] / 1024.0
- end
-
- # Ruby 1.9 with total_malloc_allocated_size patch
- elsif GC.respond_to?(:malloc_total_allocated_size)
- def measure
- GC.total_malloc_allocated_size / 1024.0
- end
-
- # Ruby 1.9 unpatched
- elsif GC.respond_to?(:malloc_allocated_size)
- def measure
- GC.malloc_allocated_size / 1024.0
- end
-
- # Ruby 1.9 + GC profiler patch
- elsif defined?(GC::Profiler)
+ # Ruby 1.9 + extended GC profiler patch
+ if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data)
def measure
GC.enable
GC.start
@@ -370,6 +344,12 @@ begin
GC.disable
kb
end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_memory)
+ def measure
+ RubyProf.measure_memory / 1024.0
+ end
end
def format(measurement)
@@ -380,27 +360,21 @@ begin
class Objects < Base
Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
- if RubyProf.respond_to?(:measure_allocations)
- def measure
- RubyProf.measure_allocations
- end
-
- # Ruby 1.8 + railsbench patch
- elsif ObjectSpace.respond_to?(:allocated_objects)
- def measure
- ObjectSpace.allocated_objects
- end
-
- # Ruby 1.9 + GC profiler patch
- elsif defined?(GC::Profiler)
+ # Ruby 1.9 + extented GC profiler patch
+ if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data)
def measure
GC.enable
GC.start
- last = GC::Profiler.data.last
- count = last[:HEAP_LIVE_OBJECTS] + last[:HEAP_FREE_OBJECTS]
+ count = GC::Profiler.data.last[:HEAP_TOTAL_OBJECTS]
GC.disable
count
end
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_allocations)
+ def measure
+ RubyProf.measure_allocations
+ end
end
def format(measurement)
@@ -411,17 +385,20 @@ begin
class GcRuns < Base
Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
- if RubyProf.respond_to?(:measure_gc_runs)
+ # Ruby 1.9 + extented GC profiler patch
+ if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data)
def measure
- RubyProf.measure_gc_runs
- end
- elsif GC.respond_to?(:collections)
- def measure
- GC.collections
+ GC.enable
+ GC.start
+ count = GC::Profiler.data.last[:GC_RUNS]
+ GC.disable
+ count
end
- elsif GC.respond_to?(:heap_info)
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_gc_runs)
def measure
- GC.heap_info['num_gc_passes']
+ RubyProf.measure_gc_runs
end
end
@@ -433,13 +410,20 @@ begin
class GcTime < Base
Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
- if RubyProf.respond_to?(:measure_gc_time)
+ # Ruby 1.9 + extented GC profiler patch
+ if defined?(GC::Profiler) and GC::Profiler.respond_to?(:data)
def measure
- RubyProf.measure_gc_time
+ GC.enable
+ GC.start
+ sec = GC::Profiler.data.inject(0) { |total, run| total += run[:GC_TIME] }
+ GC.disable
+ sec
end
- elsif GC.respond_to?(:time)
+
+ # Ruby 1.8 + ruby-prof wrapper
+ elsif RubyProf.respond_to?(:measure_gc_time)
def measure
- GC.time
+ RubyProf.measure_gc_time
end
end
@@ -452,4 +436,4 @@ begin
end
end
rescue LoadError
-end \ No newline at end of file
+end