aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/benchmarkable.rb1
-rw-r--r--activesupport/lib/active_support/configurable.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb23
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/calculations.rb49
-rw-r--r--activesupport/lib/active_support/core_ext/hash/deep_merge.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb17
-rw-r--r--activesupport/lib/active_support/core_ext/module/deprecation.rb20
-rw-r--r--activesupport/lib/active_support/core_ext/object/to_json.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/time/calculations.rb5
-rw-r--r--activesupport/lib/active_support/deprecation.rb35
-rw-r--r--activesupport/lib/active_support/deprecation/behaviors.rb56
-rw-r--r--activesupport/lib/active_support/deprecation/instance_delegator.rb24
-rw-r--r--activesupport/lib/active_support/deprecation/method_wrappers.rb70
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb71
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb33
-rw-r--r--activesupport/lib/active_support/queueing.rb133
-rw-r--r--activesupport/lib/active_support/railtie.rb9
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb5
19 files changed, 464 insertions, 123 deletions
diff --git a/activesupport/lib/active_support/benchmarkable.rb b/activesupport/lib/active_support/benchmarkable.rb
index b3c49ec169..3d8bb13c49 100644
--- a/activesupport/lib/active_support/benchmarkable.rb
+++ b/activesupport/lib/active_support/benchmarkable.rb
@@ -48,6 +48,7 @@ module ActiveSupport
# Silence the logger during the execution of the block.
def silence
+ ActiveSupport::Deprecation.warn "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
yield
ensure
diff --git a/activesupport/lib/active_support/configurable.rb b/activesupport/lib/active_support/configurable.rb
index 76a1de4077..16d2a6a290 100644
--- a/activesupport/lib/active_support/configurable.rb
+++ b/activesupport/lib/active_support/configurable.rb
@@ -92,6 +92,17 @@ module ActiveSupport
#
# User.new.allowed_access = true # => NoMethodError
# User.new.allowed_access # => NoMethodError
+ #
+ # Also you can pass a block to set up the attribute with a default value.
+ #
+ # class User
+ # include ActiveSupport::Configurable
+ # config_accessor :hair_colors do
+ # [:brown, :black, :blonde, :red]
+ # end
+ # end
+ #
+ # User.hair_colors # => [:brown, :black, :blonde, :red]
def config_accessor(*names)
options = names.extract_options!
@@ -108,6 +119,7 @@ module ActiveSupport
class_eval reader, __FILE__, reader_line unless options[:instance_reader] == false
class_eval writer, __FILE__, writer_line unless options[:instance_writer] == false
end
+ send("#{name}=", yield) if block_given?
end
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 c6eec9c486..a7551d9c64 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -9,6 +9,29 @@ class Date
include DateAndTime::Calculations
class << self
+ attr_accessor :beginning_of_week_default
+
+ # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=).
+ # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>.
+ # If no config.beginning_of_week was specified, returns :monday.
+ def beginning_of_week
+ Thread.current[:beginning_of_week] || beginning_of_week_default || :monday
+ end
+
+ # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread.
+ #
+ # This method accepts any of the following day symbols:
+ # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday
+ def beginning_of_week=(week_start)
+ Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start)
+ end
+
+ # Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol.
+ def find_beginning_of_week!(week_start)
+ raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.keys.include?(week_start)
+ week_start
+ end
+
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
def yesterday
::Date.current.yesterday
diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
index e703fca7a7..1f78b9eb5a 100644
--- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
@@ -109,10 +109,11 @@ module DateAndTime
alias :at_beginning_of_year :beginning_of_year
# Returns a new date/time representing the given day in the next week.
- # Default is :monday.
+ # Week is assumed to start on +start_day+, default is
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
# DateTime objects have their time set to 0:00.
- def next_week(day = :monday)
- first_hour{ weeks_since(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) }
+ def next_week(start_day = Date.beginning_of_week)
+ first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(start_day)) }
end
# Short-hand for months_since(1).
@@ -131,10 +132,11 @@ module DateAndTime
end
# Returns a new date/time representing the given day in the previous week.
- # Default is :monday.
+ # Week is assumed to start on +start_day+, default is
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
# DateTime objects have their time set to 0:00.
- def prev_week(day = :monday)
- first_hour{ weeks_ago(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) }
+ def prev_week(start_day = Date.beginning_of_week)
+ first_hour{ weeks_ago(1).beginning_of_week.days_since(days_span(start_day)) }
end
alias_method :last_week, :prev_week
@@ -157,31 +159,44 @@ module DateAndTime
alias_method :last_year, :prev_year
# Returns the number of days to the start of the week on the given day.
- # Default is :monday.
- def days_to_week_start(start_day = :monday)
+ # Week is assumed to start on +start_day+, default is
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
+ def days_to_week_start(start_day = Date.beginning_of_week)
start_day_number = DAYS_INTO_WEEK[start_day]
current_day_number = wday != 0 ? wday - 1 : 6
(current_day_number - start_day_number) % 7
end
# Returns a new date/time representing the start of this week on the given day.
- # Default is :monday.
- # DateTime objects have their time set to 0:00.
- def beginning_of_week(start_day = :monday)
+ # Week is assumed to start on +start_day+, default is
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
+ # +DateTime+ objects have their time set to 0:00.
+ def beginning_of_week(start_day = Date.beginning_of_week)
result = days_ago(days_to_week_start(start_day))
acts_like?(:time) ? result.midnight : result
end
alias :at_beginning_of_week :beginning_of_week
- alias :monday :beginning_of_week
+
+ # Returns Monday of this week assuming that week starts on Monday.
+ # +DateTime+ objects have their time set to 0:00.
+ def monday
+ beginning_of_week(:monday)
+ end
# Returns a new date/time representing the end of this week on the given day.
- # Default is :monday (i.e end of Sunday).
+ # Week is assumed to start on +start_day+, default is
+ # +Date.beginning_of_week+ or +config.beginning_of_week+ when set.
# DateTime objects have their time set to 23:59:59.
- def end_of_week(start_day = :monday)
+ def end_of_week(start_day = Date.beginning_of_week)
last_hour{ days_since(6 - days_to_week_start(start_day)) }
end
alias :at_end_of_week :end_of_week
- alias :sunday :end_of_week
+
+ # Returns Sunday of this week assuming that week starts on Monday.
+ # +DateTime+ objects have their time set to 23:59:59.
+ def sunday
+ end_of_week(:monday)
+ end
# Returns a new date/time representing the end of the month.
# DateTime objects will have a time set to 23:59:59.
@@ -209,5 +224,9 @@ module DateAndTime
result = yield
acts_like?(:time) ? result.end_of_day : result
end
+
+ def days_span(day)
+ (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
index 485f88cc06..83f0c87b04 100644
--- a/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
+++ b/activesupport/lib/active_support/core_ext/hash/deep_merge.rb
@@ -6,15 +6,21 @@ class Hash
#
# h1.deep_merge(h2) #=> {:x => {:y => [7, 8, 9]}, :z => "xyz"}
# h2.deep_merge(h1) #=> {:x => {:y => [4, 5, 6]}, :z => [7, 8, 9]}
- def deep_merge(other_hash)
- dup.deep_merge!(other_hash)
+ # h1.deep_merge(h2) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
+ # #=> {:x => {:y => [4, 5, 6, 7, 8, 9]}, :z => [7, 8, 9, "xyz"]}
+ def deep_merge(other_hash, &block)
+ dup.deep_merge!(other_hash, &block)
end
# Same as +deep_merge+, but modifies +self+.
- def deep_merge!(other_hash)
+ def deep_merge!(other_hash, &block)
other_hash.each_pair do |k,v|
tv = self[k]
- self[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v
+ if tv.is_a?(Hash) && v.is_a?(Hash)
+ self[k] = tv.deep_merge(v, &block)
+ else
+ self[k] = block && tv ? block.call(k, tv, v) : v
+ end
end
self
end
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 55966ffd15..e608eeaf42 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -52,6 +52,18 @@ class Module
# Foo.new.min # => 4
# Foo.new.max # => 11
#
+ # It's also possible to delegate a method to the class by using +:class+:
+ #
+ # class Foo
+ # def self.hello
+ # "world"
+ # end
+ #
+ # delegate :hello, to: :class
+ # end
+ #
+ # Foo.new.hello # => "world"
+ #
# Delegates can optionally be prefixed using the <tt>:prefix</tt> option. If the value
# is <tt>true</tt>, the delegate methods are prefixed with the name of the object being
# delegated to.
@@ -103,7 +115,7 @@ class Module
def delegate(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options[:to]
- raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter).'
+ raise ArgumentError, 'Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, to: :greeter).'
end
prefix, allow_nil = options.values_at(:prefix, :allow_nil)
@@ -122,6 +134,9 @@ class Module
file, line = caller.first.split(':', 2)
line = line.to_i
+ to = to.to_s
+ to = 'self.class' if to == 'class'
+
methods.each do |method|
# Attribute writer methods only accept one argument. Makes sure []=
# methods still accept two arguments.
diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb
index 4f629240fe..34ec6a3d8f 100644
--- a/activesupport/lib/active_support/core_ext/module/deprecation.rb
+++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb
@@ -1,10 +1,24 @@
require 'active_support/deprecation/method_wrappers'
class Module
- # Declare that a method has been deprecated.
# deprecate :foo
- # deprecate bar: 'message'
- # deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'
+ # deprecate :bar => 'message'
+ # deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
+ #
+ # You can also use custom deprecator instance:
+ #
+ # deprecate :foo, :deprecator => MyLib::Deprecator.new
+ # deprecate :foo, :bar => "warning!", :deprecator => MyLib::Deprecator.new
+ #
+ # \Custom deprecators must respond to <tt>deprecation_warning(deprecated_method_name, message, caller_backtrace)</tt>
+ # method where you can implement your custom warning behavior.
+ #
+ # class MyLib::Deprecator
+ # def deprecation_warning(deprecated_method_name, message, caller_backtrace)
+ # message = "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
+ # Kernel.warn message
+ # end
+ # end
def deprecate(*method_names)
ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
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
index e7dc60a612..83cc8066e7 100644
--- a/activesupport/lib/active_support/core_ext/object/to_json.rb
+++ b/activesupport/lib/active_support/core_ext/object/to_json.rb
@@ -17,3 +17,11 @@ end
end
end
end
+
+module Process
+ class Status
+ def as_json(options = nil)
+ { :exitstatus => exitstatus, :pid => pid }
+ end
+ 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 7d9e5bbe7d..5f85cedcf5 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -3,7 +3,7 @@ require 'active_support/core_ext/kernel/singleton_class'
class ERB
module Util
- HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#x27;' }
+ HTML_ESCAPE = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
JSON_ESCAPE = { '&' => '\u0026', '>' => '\u003E', '<' => '\u003C' }
HTML_ESCAPE_ONCE_REGEXP = /["><']|&(?!([a-zA-Z]+|(#\d+));)/
JSON_ESCAPE_REGEXP = /[&"><]/
diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb
index 359f6fa716..e3665cd896 100644
--- a/activesupport/lib/active_support/core_ext/time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -172,8 +172,9 @@ class Time
beginning_of_day..end_of_day
end
- # Returns a Range representing the whole week of the current time. Week starts on start_day (default is :monday, i.e. end of Sunday).
- def all_week(start_day = :monday)
+ # Returns a Range representing the whole week of the current time.
+ # Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set.
+ def all_week(start_day = Date.beginning_of_week)
beginning_of_week(start_day)..end_of_week(start_day)
end
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index e3b4a7240e..b3f5fde335 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -1,19 +1,34 @@
require 'active_support/core_ext/module/deprecation'
+require 'active_support/deprecation/instance_delegator'
require 'active_support/deprecation/behaviors'
require 'active_support/deprecation/reporting'
require 'active_support/deprecation/method_wrappers'
require 'active_support/deprecation/proxy_wrappers'
+require 'singleton'
module ActiveSupport
- module Deprecation
- class << self
- # The version the deprecated behavior will be removed, by default.
- attr_accessor :deprecation_horizon
- end
- self.deprecation_horizon = '4.1'
+ # \Deprecation specifies the API used by Rails to deprecate methods, instance
+ # variables, objects and constants.
+ class Deprecation
+ include Singleton
+ include InstanceDelegator
+ include Behavior
+ include Reporting
+ include MethodWrapper
+
+ # The version the deprecated behavior will be removed, by default.
+ attr_accessor :deprecation_horizon
- # By default, warnings are not silenced and debugging is off.
- self.silenced = false
- self.debug = false
+ # It accepts two parameters on initialization. The first is an version of library
+ # and the second is an library name
+ #
+ # ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
+ def initialize(deprecation_horizon = '4.1', gem_name = 'Rails')
+ self.gem_name = gem_name
+ self.deprecation_horizon = deprecation_horizon
+ # By default, warnings are not silenced and debugging is off.
+ self.silenced = false
+ self.debug = false
+ end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb
index 6bc3c7e212..90db180124 100644
--- a/activesupport/lib/active_support/deprecation/behaviors.rb
+++ b/activesupport/lib/active_support/deprecation/behaviors.rb
@@ -1,8 +1,32 @@
require "active_support/notifications"
module ActiveSupport
- module Deprecation
- class << self
+ class Deprecation
+ # Default warning behaviors per Rails.env.
+ DEFAULT_BEHAVIORS = {
+ :stderr => Proc.new { |message, callstack|
+ $stderr.puts(message)
+ $stderr.puts callstack.join("\n ") if debug
+ },
+ :log => Proc.new { |message, callstack|
+ logger =
+ if defined?(Rails) && Rails.logger
+ Rails.logger
+ else
+ require 'active_support/logger'
+ ActiveSupport::Logger.new($stderr)
+ end
+ logger.warn message
+ logger.debug callstack.join("\n ") if debug
+ },
+ :notify => Proc.new { |message, callstack|
+ ActiveSupport::Notifications.instrument("deprecation.rails",
+ :message => message, :callstack => callstack)
+ },
+ :silence => Proc.new { |message, callstack| }
+ }
+
+ module Behavior
# Whether to print a backtrace along with the warning.
attr_accessor :debug
@@ -16,9 +40,9 @@ module ActiveSupport
#
# Available behaviors:
#
- # [+stderr+] Log all deprecation warnings to <tt>$stderr</tt>.
+ # [+stderr+] Log all deprecation warnings to +$stderr+.
# [+log+] Log all deprecation warnings to +Rails.logger+.
- # [+notify+] Use <tt>ActiveSupport::Notifications</tt> to notify +deprecation.rails+.
+ # [+notify+] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
# [+silence+] Do nothing.
#
# Setting behaviors only affects deprecations that happen after boot time.
@@ -35,29 +59,5 @@ module ActiveSupport
@behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
end
end
-
- # Default warning behaviors per Rails.env.
- DEFAULT_BEHAVIORS = {
- :stderr => Proc.new { |message, callstack|
- $stderr.puts(message)
- $stderr.puts callstack.join("\n ") if debug
- },
- :log => Proc.new { |message, callstack|
- logger =
- if defined?(Rails) && Rails.logger
- Rails.logger
- else
- require 'active_support/logger'
- ActiveSupport::Logger.new($stderr)
- end
- logger.warn message
- logger.debug callstack.join("\n ") if debug
- },
- :notify => Proc.new { |message, callstack|
- ActiveSupport::Notifications.instrument("deprecation.rails",
- :message => message, :callstack => callstack)
- },
- :silence => Proc.new { |message, callstack| }
- }
end
end
diff --git a/activesupport/lib/active_support/deprecation/instance_delegator.rb b/activesupport/lib/active_support/deprecation/instance_delegator.rb
new file mode 100644
index 0000000000..ff240cb887
--- /dev/null
+++ b/activesupport/lib/active_support/deprecation/instance_delegator.rb
@@ -0,0 +1,24 @@
+require 'active_support/core_ext/kernel/singleton_class'
+require 'active_support/core_ext/module/delegation'
+
+module ActiveSupport
+ class Deprecation
+ module InstanceDelegator
+ def self.included(base)
+ base.extend(ClassMethods)
+ base.public_class_method :new
+ end
+
+ module ClassMethods
+ def include(included_module)
+ included_module.instance_methods.each { |m| method_added(m) }
+ super
+ end
+
+ def method_added(method_name)
+ singleton_class.delegate(method_name, to: :instance)
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
index 257b70e34a..d3907b03e5 100644
--- a/activesupport/lib/active_support/deprecation/method_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -2,45 +2,41 @@ require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/array/extract_options'
module ActiveSupport
- module Deprecation
- # Declare that a method has been deprecated.
- #
- # module Fred
- # extend self
- #
- # def foo; end
- # def bar; end
- # def baz; end
- # end
- #
- # ActiveSupport::Deprecation.deprecate_methods(Fred, :foo, bar: :qux, baz: 'use Bar#baz instead')
- # # => [:foo, :bar, :baz]
- #
- # Fred.foo
- # # => "DEPRECATION WARNING: foo is deprecated and will be removed from Rails 4.1."
- #
- # Fred.bar
- # # => "DEPRECATION WARNING: bar is deprecated and will be removed from Rails 4.1 (use qux instead)."
- #
- # Fred.baz
- # # => "DEPRECATION WARNING: baz is deprecated and will be removed from Rails 4.1 (use Bar#baz instead)."
- def self.deprecate_methods(target_module, *method_names)
- options = method_names.extract_options!
- method_names += options.keys
+ class Deprecation
+ module MethodWrapper
+ # Declare that a method has been deprecated.
+ #
+ # module Fred
+ # extend self
+ #
+ # def foo; end
+ # def bar; end
+ # def baz; end
+ # end
+ #
+ # ActiveSupport::Deprecation.deprecate_methods(Fred, :foo, bar: :qux, baz: 'use Bar#baz instead')
+ # # => [:foo, :bar, :baz]
+ #
+ # Fred.foo
+ # # => "DEPRECATION WARNING: foo is deprecated and will be removed from Rails 4.1."
+ #
+ # Fred.bar
+ # # => "DEPRECATION WARNING: bar is deprecated and will be removed from Rails 4.1 (use qux instead)."
+ #
+ # Fred.baz
+ # # => "DEPRECATION WARNING: baz is deprecated and will be removed from Rails 4.1 (use Bar#baz instead)."
+ def deprecate_methods(target_module, *method_names)
+ options = method_names.extract_options!
+ deprecator = options.delete(:deprecator) || ActiveSupport::Deprecation.instance
+ method_names += options.keys
- method_names.each do |method_name|
- target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
- target_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
- def #{target}_with_deprecation#{punctuation}(*args, &block)
- ::ActiveSupport::Deprecation.warn(
- ::ActiveSupport::Deprecation.deprecated_method_warning(
- :#{method_name},
- #{options[method_name].inspect}),
- caller
- )
- send(:#{target}_without_deprecation#{punctuation}, *args, &block)
+ method_names.each do |method_name|
+ target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
+ target_module.send(:define_method, "#{target}_with_deprecation#{punctuation}") do |*args, &block|
+ deprecator.deprecation_warning(method_name, options[method_name], caller)
+ send(:"#{target}_without_deprecation#{punctuation}", *args, &block)
end
- end_eval
+ end
end
end
end
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index a65fcafb44..17e69c34a5 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -1,7 +1,7 @@
require 'active_support/inflector/methods'
module ActiveSupport
- module Deprecation
+ class Deprecation
class DeprecationProxy #:nodoc:
def self.new(*args, &block)
object = args.first
@@ -25,10 +25,20 @@ module ActiveSupport
end
end
- class DeprecatedObjectProxy < DeprecationProxy #:nodoc:
- def initialize(object, message)
+ # This DeprecatedObjectProxy transforms object to depracated object.
+ #
+ # @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!")
+ # @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!", deprecator_instance)
+ #
+ # When someone execute any method expect +inspect+ on proxy object this will
+ # trigger +warn+ method on +deprecator_instance+.
+ #
+ # Default deprecator is <tt>ActiveSupport::Deprecation</tt>
+ class DeprecatedObjectProxy < DeprecationProxy
+ def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
@object = object
@message = message
+ @deprecator = deprecator
end
private
@@ -37,15 +47,40 @@ module ActiveSupport
end
def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn(@message, callstack)
+ @deprecator.warn(@message, callstack)
end
end
- # Stand-in for <tt>@request</tt>, <tt>@attributes</tt>, <tt>@params</tt>, etc.
- # which emits deprecation warnings on any method call (except +inspect+).
- class DeprecatedInstanceVariableProxy < DeprecationProxy #:nodoc:
- def initialize(instance, method, var = "@#{method}")
- @instance, @method, @var = instance, method, var
+ # This DeprecatedInstanceVariableProxy transforms instance variable to
+ # depracated instance variable.
+ #
+ # class Example
+ # def initialize(deprecator)
+ # @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
+ # @_request = :a_request
+ # end
+ #
+ # def request
+ # @_request
+ # end
+ #
+ # def old_request
+ # @request
+ # end
+ # end
+ #
+ # When someone execute any method on @request variable this will trigger
+ # +warn+ method on +deprecator_instance+ and will fetch <tt>@_request</tt>
+ # variable via +request+ method and execute the same method on non-proxy
+ # instance variable.
+ #
+ # Default deprecator is <tt>ActiveSupport::Deprecation</tt>.
+ class DeprecatedInstanceVariableProxy < DeprecationProxy
+ def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
+ @instance = instance
+ @method = method
+ @var = var
+ @deprecator = deprecator
end
private
@@ -54,14 +89,24 @@ module ActiveSupport
end
def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
+ @deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
end
end
- class DeprecatedConstantProxy < DeprecationProxy #:nodoc:all
- def initialize(old_const, new_const)
+ # This DeprecatedConstantProxy transforms constant to depracated constant.
+ #
+ # OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST')
+ # OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST', deprecator_instance)
+ #
+ # When someone use old constant this will trigger +warn+ method on
+ # +deprecator_instance+.
+ #
+ # Default deprecator is <tt>ActiveSupport::Deprecation</tt>.
+ class DeprecatedConstantProxy < DeprecationProxy
+ def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance)
@old_const = old_const
@new_const = new_const
+ @deprecator = deprecator
end
def class
@@ -74,7 +119,7 @@ module ActiveSupport
end
def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
+ @deprecator.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
end
end
end
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index 874270c1c2..1ce54d9381 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -1,7 +1,10 @@
module ActiveSupport
- module Deprecation
- class << self
+ class Deprecation
+ module Reporting
+ # Whether to print a message (silent mode)
attr_accessor :silenced
+ # Name of gem where method is deprecated
+ attr_accessor :gem_name
# Outputs a deprecation warning to the output configured by
# <tt>ActiveSupport::Deprecation.behavior</tt>.
@@ -31,16 +34,30 @@ module ActiveSupport
@silenced = old_silenced
end
- def deprecated_method_warning(method_name, message = nil)
- warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
- case message
- when Symbol then "#{warning} (use #{message} instead)"
- when String then "#{warning} (#{message})"
- else warning
+ def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = caller)
+ deprecated_method_warning(deprecated_method_name, message).tap do |msg|
+ warn(msg, caller_backtrace)
end
end
private
+ # Outputs a deprecation warning message
+ #
+ # ActiveSupport::Deprecation.deprecated_method_warning(:method_name)
+ # # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
+ # ActiveSupport::Deprecation.deprecated_method_warning(:method_name, :another_method)
+ # # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (use another_method instead)"
+ # ActiveSupport::Deprecation.deprecated_method_warning(:method_name, "Optional message")
+ # # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (Optional message)"
+ def deprecated_method_warning(method_name, message = nil)
+ warning = "#{method_name} is deprecated and will be removed from #{gem_name} #{deprecation_horizon}"
+ case message
+ when Symbol then "#{warning} (use #{message} instead)"
+ when String then "#{warning} (#{message})"
+ else warning
+ end
+ end
+
def deprecation_message(callstack, message = nil)
message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
message += '.' unless message =~ /\.$/
diff --git a/activesupport/lib/active_support/queueing.rb b/activesupport/lib/active_support/queueing.rb
new file mode 100644
index 0000000000..0a4ab05b78
--- /dev/null
+++ b/activesupport/lib/active_support/queueing.rb
@@ -0,0 +1,133 @@
+require 'delegate'
+require 'thread'
+
+module ActiveSupport
+ # A Queue that simply inherits from STDLIB's Queue. When this
+ # queue is used, Rails automatically starts a job runner in a
+ # background thread.
+ class Queue < ::Queue
+ attr_writer :consumer
+
+ def initialize(consumer_options = {})
+ super()
+ @consumer_options = consumer_options
+ end
+
+ def consumer
+ @consumer ||= ThreadedQueueConsumer.new(self, @consumer_options)
+ end
+
+ # Drain the queue, running all jobs in a different thread. This method
+ # may not be available on production queues.
+ def drain
+ # run the jobs in a separate thread so assumptions of synchronous
+ # jobs are caught in test mode.
+ consumer.drain
+ end
+ end
+
+ class SynchronousQueue < Queue
+ def push(job)
+ super.tap { drain }
+ end
+ alias << push
+ alias enq push
+ end
+
+ # In test mode, the Rails queue is backed by an Array so that assertions
+ # can be made about its contents. The test queue provides a +jobs+
+ # method to make assertions about the queue's contents and a +drain+
+ # method to drain the queue and run the jobs.
+ #
+ # Jobs are run in a separate thread to catch mistakes where code
+ # assumes that the job is run in the same thread.
+ class TestQueue < Queue
+ # Get a list of the jobs off this queue. This method may not be
+ # available on production queues.
+ def jobs
+ @que.dup
+ end
+
+ # Marshal and unmarshal job before pushing it onto the queue. This will
+ # raise an exception on any attempts in tests to push jobs that can't (or
+ # shouldn't) be marshalled.
+ def push(job)
+ super Marshal.load(Marshal.dump(job))
+ end
+ end
+
+ # A container for multiple queues. This class delegates to a default Queue
+ # so that <tt>Rails.queue.push</tt> and friends will Just Work. To use this class
+ # with multiple queues:
+ #
+ # # In your configuration:
+ # Rails.queue[:image_queue] = SomeQueue.new
+ # Rails.queue[:mail_queue] = SomeQueue.new
+ #
+ # # In your app code:
+ # Rails.queue[:mail_queue].push SomeJob.new
+ #
+ class QueueContainer < DelegateClass(::Queue)
+ def initialize(default_queue)
+ @queues = { :default => default_queue }
+ super(default_queue)
+ end
+
+ def [](queue_name)
+ @queues[queue_name]
+ end
+
+ def []=(queue_name, queue)
+ @queues[queue_name] = queue
+ end
+ end
+
+ # The threaded consumer will run jobs in a background thread in
+ # development mode or in a VM where running jobs on a thread in
+ # production mode makes sense.
+ #
+ # When the process exits, the consumer pushes a nil onto the
+ # queue and joins the thread, which will ensure that all jobs
+ # are executed before the process finally dies.
+ class ThreadedQueueConsumer
+ def self.start(*args)
+ new(*args).start
+ end
+
+ def initialize(queue, options = {})
+ @queue = queue
+ @logger = options[:logger]
+ end
+
+ def start
+ @thread = Thread.new { consume }
+ self
+ end
+
+ def shutdown
+ @queue.push nil
+ @thread.join
+ end
+
+ def drain
+ run(@queue.pop) until @queue.empty?
+ end
+
+ def consume
+ while job = @queue.pop
+ run job
+ end
+ end
+
+ def run(job)
+ job.run
+ rescue Exception => exception
+ handle_exception job, exception
+ end
+
+ def handle_exception(job, exception)
+ raise unless @logger
+ @logger.error "Job Error: #{exception.message}\n#{exception.backtrace.join("\n")}"
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index bf9e889204..133aa6a054 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -27,6 +27,15 @@ module ActiveSupport
Time.zone_default = zone_default
end
+ # Sets the default week start
+ # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
+ initializer "active_support.initialize_beginning_of_week" do |app|
+ require 'active_support/core_ext/date/calculations'
+ beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week)
+
+ Date.beginning_of_week_default = beginning_of_week_default
+ end
+
initializer "active_support.set_configs" do |app|
app.config.active_support.each do |k, v|
k = "#{k}="
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index eaf484fad4..b931de3fac 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -173,7 +173,10 @@ module ActiveSupport
# +formatted_offset+, respectively, before passing to Time#strftime, so
# that zone information is correct
def strftime(format)
- format = format.gsub('%Z', zone).gsub('%z', formatted_offset(false))
+ format = format.gsub('%Z', zone)
+ .gsub('%z', formatted_offset(false))
+ .gsub('%:z', formatted_offset(true))
+ .gsub('%::z', formatted_offset(true) + ":00")
time.strftime(format)
end