Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
## Rails 4.0.0 (unreleased) ##

* ActiveSupport::Deprecation is now a class. It is possible to create an instance
of deprecator. Backwards compatibility has been preserved.

You can choose which instance of the deprecator will be used.

deprecate :method_name, :deprecator => deprecator_instance

You can use ActiveSupport::Deprecation in your gem.

require 'active_support/deprecation'
require 'active_support/core_ext/module/deprecation'

class MyGem
def old_method
end
deprecate :old_method => :new_method, :deprecator => deprecator

def new_method
end

def self.deprecator
ActiveSupport::Deprecation.new('2.0', 'MyGem')
end
end

MyGem.new.old_method

DEPRECATION WARNING: old_method is deprecated and will be removed from MyGem 2.0
(use new_method instead). (called from <main> at file.rb:18)

*Piotr Niełacny & Robert Pankowecki*

* `ERB::Util.html_escape` encodes single quote as `#39`. Decimal form has better support in old browsers. *Kalys Osmonov*

* `ActiveSupport::Callbacks`: deprecate monkey patch of object callbacks.
Expand Down
34 changes: 33 additions & 1 deletion activesupport/lib/active_support/core_ext/module/deprecation.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
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!'
#
# You can use custom deprecator instance
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use a custom deprecator object that responds to +warn+ and +deprecated_method_warning+. This is useful when you use +ActiveSupport::Deprecation+ in your own libraries and want to customize deprecation behavior.

# deprecate :foo, :deprecator => MyLib::Deprecator.new
# deprecate :foo, :bar => "warning!", :deprecator => MyLib::Deprecator.new
#
# \Custom deprecators must respond to one method
# [deprecation_warning(deprecated_method_name, message, caller_backtrace)] will be called with the deprecated
# method name, the message it was declared
# with and caller_backtrace. Implement
# whatever warning behavior you like here.
#
# Example
# 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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove whitespaces between the method and class declaration, there's no need for them ✂️

#
# module MyLib
# mattr_accessor :deprecator
# self.deprecator = Deprecator.new
# end
#
# When we deprecate method
# class MyLib::Bar
# deprecate :foo => "this is very old method", :deprecator => MyLib.deprecator
# end
#
# It will build deprecation message and invoke deprecator warning by calling
# MyLib.deprecator.deprecation_warning(:foo, "this is a very old method", caller)
def deprecate(*method_names)
ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
end
Expand Down
41 changes: 31 additions & 10 deletions activesupport/lib/active_support/deprecation.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
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.
# The API depends on four methods:
#
# * +initialize+ which expects two parameters
# described below;
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
#
# == Example
#
# 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
end
58 changes: 29 additions & 29 deletions activesupport/lib/active_support/deprecation/behaviors.rb
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -16,9 +40,9 @@ def behavior
#
# 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.
Expand All @@ -28,36 +52,12 @@ def behavior
# ActiveSupport::Deprecation.behavior = :stderr
# ActiveSupport::Deprecation.behavior = [:stderr, :log]
# ActiveSupport::Deprecation.behavior = MyCustomHandler
# ActiveSupport::Deprecation.behavior = proc { |message, callstack|
# ActiveSupport::Deprecation.behavior = proc { |message, callstack|
# # custom stuff
# }
def behavior=(behavior)
@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
24 changes: 24 additions & 0 deletions activesupport/lib/active_support/deprecation/instance_delegator.rb
Original file line number Diff line number Diff line change
@@ -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
70 changes: 33 additions & 37 deletions activesupport/lib/active_support/deprecation/method_wrappers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,41 @@
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
Expand Down
Loading