diff options
author | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-09-13 04:47:03 -0700 |
---|---|---|
committer | Carlos Antonio da Silva <carlosantoniodasilva@gmail.com> | 2012-09-13 04:47:03 -0700 |
commit | 01ef633f753cbc97ecd89b464af33e80fd0ca917 (patch) | |
tree | 515425716f332400ee5df8fb6515cc0c26ce6a0a /activesupport/lib | |
parent | c4b857299b3322572b006d825bb9dc9912101e99 (diff) | |
parent | 71993c6f9770b1350aa41fe8c68f1dd2c7800403 (diff) | |
download | rails-01ef633f753cbc97ecd89b464af33e80fd0ca917.tar.gz rails-01ef633f753cbc97ecd89b464af33e80fd0ca917.tar.bz2 rails-01ef633f753cbc97ecd89b464af33e80fd0ca917.zip |
Merge pull request #6348 from LTe/no_global_depreactations
Allow ActiveSupport::Deprecation features to be used by rails applications and library authors
Diffstat (limited to 'activesupport/lib')
7 files changed, 231 insertions, 98 deletions
diff --git a/activesupport/lib/active_support/core_ext/module/deprecation.rb b/activesupport/lib/active_support/core_ext/module/deprecation.rb index 9e77ac3c45..9affd38baa 100644 --- a/activesupport/lib/active_support/core_ext/module/deprecation.rb +++ b/activesupport/lib/active_support/core_ext/module/deprecation.rb @@ -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 + # 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 + # + # 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 diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index e3b4a7240e..678cbbcbf2 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -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
\ 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 fc962dcb57..b4c8a0e92d 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. @@ -28,36 +52,12 @@ module ActiveSupport # 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 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..2b8282c34e 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,21 @@ module ActiveSupport end end - class DeprecatedObjectProxy < DeprecationProxy #:nodoc: - def initialize(object, message) + # This DeprecatedObjectProxy transforms object to depracated object. + # + # Example + # @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!") + # Example with custom deprecator + # @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 ActiveSupport::Deprecation + class DeprecatedObjectProxy < DeprecationProxy + def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance) @object = object @message = message + @deprecator = deprecator end private @@ -37,15 +48,38 @@ 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. + # + # Example + # 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 @_request variable via +request+ method and execute the same method on non-proxy instance variable. + # + # Default deprecator is ActiveSupport::Deprecation + 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 +88,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. + # + # Example + # OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST') + # Example with custom deprecator + # 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 ActiveSupport::Deprecation + 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 +118,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 a1e9618084..cf91ca1acb 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,29 @@ 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 |message| + warn(message, 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 =~ /\.$/ |