Skip to content
This repository

Allow ActiveSupport::Deprecation features to be used by rails applications and library authors #6348

Merged
merged 2 commits into from over 1 year ago

7 participants

Piotr Niełacny Rafael Mendonça França Jeremy Kemper Robert Pankowecki Steve Klabnik Carlos Antonio da Silva Peter Suschlik
Piotr Niełacny
LTe commented

Updated version of #2310

Jeremy Kemper
Owner
jeremy commented
  1. If we're exposing this for reuse, we need docs! How should a library author use this?
  2. Feels like libraries using separate deprecators should be working with instances of a class rather than extending with a module that injects a bunch of behavior, including its internal state. Could make ActiveSupport::Deprecation a class (without breaking API) and delegate the existing toplevel methods to a singleton ActiveSupport::Deprecation.instance
  3. The #deprecator instance method may be unnecessary. Looks like the only reason we need it is so the deprecated method wrapper can refer to it. It'd be cleaner to pass a deprecator instance and reference it directly from the method wrapper (using define_method instead of class_eval)
Piotr Niełacny
LTe commented

@jeremy done :)

activesupport/lib/active_support/deprecation/behaviors.rb
((13 lines not shown))
38 37
 
39  
-    # Default warning behaviors per Rails.env.
40  
-    DEFAULT_BEHAVIORS = {
1
Jeremy Kemper Owner
jeremy added a note

Should probably leave these as a constant since it acts as public API now. People add behaviors to this hash directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jeremy Kemper
Owner
jeremy commented

@LTe Very nice! Looking good.

activesupport/lib/active_support/deprecation/proxy_wrappers.rb
((6 lines not shown))
58 92
         end
59 93
     end
60 94
 
61  
-    class DeprecatedConstantProxy < DeprecationProxy #:nodoc:all
62  
-      def initialize(old_const, new_const)
  95
+    # This DeprecatedConstantProxy transforms constant to depracated constant.
  96
+    #
  97
+    # Example
  98
+    #   OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST')
  99
+    # Example with custom deprecator
  100
+    #   OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST'. deprecator_instance)
1
Carlos Antonio da Silva Owner

Typo: . instead of , after NEW_CONST.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/deprecation/reporting.rb
... ...
@@ -22,6 +23,13 @@ def silence
22 23
         @silenced = old_silenced
23 24
       end
24 25
 
  26
+      # Outputs a deprecation warning message
  27
+      #   ActiveSupport::Deprecation.deprecated_method_warning(:method_name)
  28
+      #   # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
  29
+      #   ActiveSupport::Deprecation.deprecated_method_warning(:method_name, :another_method)
  30
+      #   # =>  "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (use another_method instead)"
1
Carlos Antonio da Silva Owner

Indent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/test/deprecation_test.rb
((116 lines not shown))
  301
+        def message
  302
+          ActiveSupport::Deprecation.warn 'warning in error message'
  303
+          super
  304
+        end
  305
+      end
  306
+
  307
+      raise error_class.new('hmm')
  308
+
  309
+    rescue => e
  310
+      error = Test::Unit::Error.new('testing ur doodz', e)
  311
+      assert_not_deprecated { error.message }
  312
+      assert_nil @last_message
  313
+    end
  314
+  end
  315
+
  316
+
1
Carlos Antonio da Silva Owner

Two lines :scissors:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
((17 lines not shown))
  21
+  #         "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  22
+  #       end
  23
+  #
  24
+  #       def warn(message, backtrace)
  25
+  #         puts(message)
  26
+  #       end
  27
+  #     end
  28
+  #   end
  29
+  #
  30
+  # When we deprecate method
  31
+  #   deprecate :foo => "this is very old method", :deprecator => CustomClass::Deprecator.instance
  32
+  #
  33
+  # It will execute
  34
+  #   CustomClass::Deprecator.instance.deprecated_method_warning(:foo, "this is very old method").tap |message|
  35
+  #     CustomClass::Deprecator.instance.warn(message, backtrace)
  36
+  #   end
2
Carlos Antonio da Silva Owner

The docs are pretty good, but there's no mention of instance in CustomClass::Deprecator, this may confuse people. Perhaps you can just use new instead of instance, or add the method or singleton there to show how it'd look like?

Jeremy Kemper Owner
jeremy added a note

Agree -- no need to introduce a singleton for the custom case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Piotr Niełacny
LTe commented

@carlosantoniodasilva @jeremy thanks for feedback!

Robert Pankowecki
paneq commented

What do you think about it:

module ActiveSupport
  class Deprecation
    def initialize(horizon = '3.2', gem_name = 'rails')
      self.deprecation_horizon = horizon
      self.gem_name = gem_name
    end
  end
end

For custom gems authors should create new instances of ActiveSupport::Deprecation to generate proper warning messages. If they use ActiveSupport::Deprecation.instance the message is going to say that something will be removed from rails which is in many cases not what the authors of gems would like to announce to the users.

These:

deprecator = ActiveSupport::Deprecation.new
deprecator.deprecation_horizon = "2.0.0"
ActiveSupport::Deprecation.new.tap{|d| d.deprecation_horizon = "2.0.0" }

seem to be unnecessary verbose to me.

ActiveSupport::Deprecation.new("2.0.0", "formtastic")

looks much better imho.

Robert Pankowecki
paneq commented

Science Fiction:

module ActiveSupport
  class Deprecation
    def initialize(horizon = default_horizon, gem_name = 'rails')
      self.deprecation_horizon = horizon
      self.gem_name = gem_name
    end

    def default_horizon
      "#{ActiveSupport::VERSION::MAJOR}.#{ActiveSupport::VERSION::MINOR + 1}"
    end
  end
end

because sometimes it should be major + 1. Or maybe it should be always major +1 and never minor + 1 ?

Piotr Niełacny
LTe commented

Now you can create instance of deprecator and create new object via new.
I like @paneq approach -- now this is simple to reuse.

About science fiction I think better solution is pass directly version to initialize method.

Robert Pankowecki
paneq commented

"About science fiction I think better solution is pass directly version to initialize method." - probably. Except for the fact that the core team needs to change this one line every time there is new rails version. I wanted to spare them this trouble in this science fiction solution :)

Piotr Niełacny
LTe commented

According to http://semver.org/ this always should be major +1

Piotr Niełacny
LTe commented

@jeremy what do you think? We can merge current implementation?

activesupport/lib/active_support/deprecation/behaviors.rb
((6 lines not shown))
20 44
       # [+log+]     Log all deprecation warnings to +Rails.logger+.
21  
-      # [+notify+]  Use <tt>ActiveSupport::Notifications</tt> to notify +deprecation.rails+.
  45
+      # [+notify]   Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
1
Jeremy Kemper Owner
jeremy added a note

[+notify+] formatting changed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/deprecation/method_wrappers.rb
... ...
@@ -2,25 +2,26 @@
2 2
 require 'active_support/core_ext/array/extract_options'
3 3
 
4 4
 module ActiveSupport
5  
-  module Deprecation
6  
-    # Declare that a method has been deprecated.
7  
-    def self.deprecate_methods(target_module, *method_names)
8  
-      options = method_names.extract_options!
9  
-      method_names += options.keys
  5
+  class Deprecation
  6
+    module MethodWrapper
  7
+      # Declare that a method has been deprecated.
  8
+      def deprecate_methods(target_module, *method_names)
  9
+        options = method_names.extract_options!
  10
+        deprecator = options.delete(:deprecator) || ActiveSupport::Deprecation
1
Jeremy Kemper Owner
jeremy added a note

ActiveSupport::Deprecation.instance here rather than rely on the instance delegator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/deprecation/proxy_wrappers.rb
... ...
@@ -25,10 +25,21 @@ def method_missing(called, *args, &block)
25 25
         end
26 26
     end
27 27
 
28  
-    class DeprecatedObjectProxy < DeprecationProxy #:nodoc:
29  
-      def initialize(object, message)
  28
+    # This DeprecatedObjectProxy transforms object to depracated object.
  29
+    #
  30
+    # Example
  31
+    #   @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!")
  32
+    # Example with custom deprecator
  33
+    #   @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!", deprecator_instance)
  34
+    #
  35
+    # When someone execute any method expect +inspect+ on proxy object this will trigger +warn+ method on +deprecator_instance+
  36
+    #
  37
+    # Default deprecator is ActiveSupport::Deprecation
  38
+    class DeprecatedObjectProxy < DeprecationProxy
  39
+      def initialize(object, message, deprecator = ActiveSupport::Deprecation)
1
Jeremy Kemper Owner
jeremy added a note

.instance here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Piotr Niełacny
LTe commented

@jeremy updated and rebased

activesupport/lib/active_support/deprecation/behaviors.rb
... ...
@@ -1,8 +1,32 @@
1 1
 require "active_support/notifications"
2 2
 
3 3
 module ActiveSupport
4  
-  module Deprecation
5  
-    class << self
  4
+  class Deprecation
  5
+    # Default warning behaviors per Rails.env.
  6
+    DEFAULT_BEHAVIORS = {
  7
+        :stderr => Proc.new { |message, callstack|
  8
+          $stderr.puts(message)
1
Jeremy Kemper Owner
jeremy added a note

Extra indentation here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jeremy Kemper jeremy commented on the diff
activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -5,6 +5,36 @@ class Module
5 5
   #   deprecate :foo
6 6
   #   deprecate :bar => 'message'
7 7
   #   deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
  8
+  #
  9
+  # You can use custom deprecator instance
1
Jeremy Kemper Owner
jeremy added a note

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
((9 lines not shown))
5 8
   #   deprecate :foo
6 9
   #   deprecate :bar => 'message'
7 10
   #   deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
  11
+  #
  12
+  # You can use custom deprecator instance
  13
+  #   deprecate :foo, :deprecator => CustomClass::Deprecator.new
  14
+  #   deprecate :foo, :bar => "warning!", :deprecator => CustomClass::Deprecator.new
  15
+  #
  16
+  # Custom deprecator instance need respond to two methods
  17
+  # [deprecated_method_warning(method_name, message)] Method will be executed with *deprecated* method name
  18
+  # [warn(message, backtrace)]  Method will accept message from *deprecated_method_warning* method and backtrace
  19
+  #
  20
+  # Example
  21
+  #   class CustomClass
  22
+  #     class Deprecator
  23
+  #       def deprecated_method_warning(method_name, message)
2
Jeremy Kemper Owner
jeremy added a note
class MyLib::Deprecator
  def warn(message, backtrace)
    Kernel.warn message
  end

  def deprecated_method_warning(method_name, message)
    "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  end
end
Jeremy Kemper Owner
jeremy added a note
module MyLib
  mattr_accessor :deprecator
  self.deprecator = Deprecator.new
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
((12 lines not shown))
  11
+  #
  12
+  # You can use custom deprecator instance
  13
+  #   deprecate :foo, :deprecator => CustomClass::Deprecator.new
  14
+  #   deprecate :foo, :bar => "warning!", :deprecator => CustomClass::Deprecator.new
  15
+  #
  16
+  # Custom deprecator instance need respond to two methods
  17
+  # [deprecated_method_warning(method_name, message)] Method will be executed with *deprecated* method name
  18
+  # [warn(message, backtrace)]  Method will accept message from *deprecated_method_warning* method and backtrace
  19
+  #
  20
+  # Example
  21
+  #   class CustomClass
  22
+  #     class Deprecator
  23
+  #       def deprecated_method_warning(method_name, message)
  24
+  #         "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  25
+  #       end
  26
+  #
1
Jeremy Kemper Owner
jeremy added a note
class MyLib::Bar
  deprecate :foo => "this is very old method", :deprecator => MyLib.deprecator
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
((18 lines not shown))
  17
+  # [deprecated_method_warning(method_name, message)] Method will be executed with *deprecated* method name
  18
+  # [warn(message, backtrace)]  Method will accept message from *deprecated_method_warning* method and backtrace
  19
+  #
  20
+  # Example
  21
+  #   class CustomClass
  22
+  #     class Deprecator
  23
+  #       def deprecated_method_warning(method_name, message)
  24
+  #         "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  25
+  #       end
  26
+  #
  27
+  #       def warn(message, backtrace)
  28
+  #         puts(message)
  29
+  #       end
  30
+  #     end
  31
+  #   end
  32
+  #
1
Jeremy Kemper Owner
jeremy added a note

It will build a deprecation warning message by calling MyLib.deprecator.deprecated_method_warning(:foo, "this is a very old method") then invoke the deprecator warning with the message and the caller's backtrace: MyLib.deprecator.warn(warning_message, caller)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -1,10 +1,43 @@
1 1
 require 'active_support/deprecation/method_wrappers'
2 2
 
3 3
 class Module
4  
-  # Declare that a method has been deprecated.
  4
+  # You can use a custom deprecator object that responds to +warn+ and +deprecated_method_warning+.
  5
+  # This is useful when you use +ActiveSupport::Deprecation+ in your own libraries and want to customize
  6
+  # deprecation behavior.
1
Jeremy Kemper Owner
jeremy added a note

Can leave these out, they're better demonstrated below

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -1,10 +1,43 @@
1 1
 require 'active_support/deprecation/method_wrappers'
2 2
 
3 3
 class Module
4  
-  # Declare that a method has been deprecated.
  4
+  # You can use a custom deprecator object that responds to +warn+ and +deprecated_method_warning+.
  5
+  # This is useful when you use +ActiveSupport::Deprecation+ in your own libraries and want to customize
  6
+  # deprecation behavior.
  7
+  #
5 8
   #   deprecate :foo
1
Jeremy Kemper Owner
jeremy added a note

Custom deprecators must respond to two methods:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -1,10 +1,43 @@
1 1
 require 'active_support/deprecation/method_wrappers'
2 2
 
3 3
 class Module
4  
-  # Declare that a method has been deprecated.
  4
+  # You can use a custom deprecator object that responds to +warn+ and +deprecated_method_warning+.
  5
+  # This is useful when you use +ActiveSupport::Deprecation+ in your own libraries and want to customize
  6
+  # deprecation behavior.
  7
+  #
5 8
   #   deprecate :foo
6 9
   #   deprecate :bar => 'message'
1
Jeremy Kemper Owner
jeremy added a note

[deprecated_method_warning(method_name, message)] will be called with the deprecated method name and the message it was declared with. Return a warning message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -1,10 +1,43 @@
1 1
 require 'active_support/deprecation/method_wrappers'
2 2
 
3 3
 class Module
4  
-  # Declare that a method has been deprecated.
  4
+  # You can use a custom deprecator object that responds to +warn+ and +deprecated_method_warning+.
  5
+  # This is useful when you use +ActiveSupport::Deprecation+ in your own libraries and want to customize
  6
+  # deprecation behavior.
  7
+  #
5 8
   #   deprecate :foo
6 9
   #   deprecate :bar => 'message'
7 10
   #   deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
1
Jeremy Kemper Owner
jeremy added a note

[warn(message, backtrace)] will be called with the message from your deprecated_method_warning method and the caller's backtrace. Implement whatever warning behavior you like here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Jeremy Kemper
Owner
jeremy commented

@LTe some comments on the documentation :)

It covers how to give a custom deprecator object, but doesn't show how you can use ActiveSupport::Deprecation.new(version, libname) yourself.

When I read through the duck type for a deprecator, having to implement two methods seems wrong, too. We call deprecator.deprecated_method_warning then pass its return value to #warn -- we could just call one method and let the deprecator handle that internally.

Robert Pankowecki
paneq commented

@jeremy - I think that's because #warn has the logic for outputing to logger, stderr, output or whatever is configured in current development environment and #deprecated_method_warning is just responsible for generting the warning. One might want to generate different warnings for his own gem but keep the logic coherent with Rails as to where they are displayed. What do you think ?

Jeremy Kemper
Owner
jeremy commented

@paneq definitely -- and a higher-level method like deprecation_warning(deprecated_method_name, message, caller_backtrace) could wrap that up. Then custom classes can implement that one method whereas subclasses of ActiveSupport::Deprecation can override just deprecated_method_warning if they like.

Piotr Niełacny
LTe commented

Updated

Piotr Niełacny
LTe commented

@jeremy what do you think about merge?

Steve Klabnik
Collaborator

@LTe it needs rebased at least, it can't be merged cleanly anymore.

Piotr Niełacny
LTe commented

@steveklabnik rebased ;-)

Steve Klabnik
Collaborator

Thanks. Let's see what @jeremy says.

Robert Pankowecki
paneq commented

What do you think @jeremy ?

Jeremy Kemper
Owner

:+1:

activesupport/lib/active_support/core_ext/module/deprecation.rb
((12 lines not shown))
  11
+  #
  12
+  # \Custom deprecators must respond to one method
  13
+  # [deprecation_warning(deprecated_method_name, message, caller_backtrace)] will be called with the deprecated
  14
+  #                                                                          method name, the message it was declared
  15
+  #                                                                          with and caller_backtrace. Implement
  16
+  #                                                                          whatever warning behavior you like here.
  17
+  #
  18
+  # Example
  19
+  #    class MyLib::Deprecator
  20
+  #
  21
+  #      def deprecation_warning(deprecated_method_name, message, caller_backtrace)
  22
+  #         message = "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  23
+  #         Kernel.warn message
  24
+  #      end
  25
+  #
  26
+  #    end
1

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
activesupport/test/deprecation_test.rb
((117 lines not shown))
  313
+    deprecator = ActiveSupport::Deprecation.new
  314
+
  315
+    deprecator.send(:deprecated_method_warning, :deprecated_method, "You are calling deprecated method").tap do |message|
  316
+      assert_match(/is deprecated and will be removed from Rails/, message)
  317
+    end
  318
+  end
  319
+
  320
+  def test_custom_gem_name
  321
+    deprecator = ActiveSupport::Deprecation.new('2.0', 'Custom')
  322
+
  323
+    deprecator.send(:deprecated_method_warning, :deprecated_method, "You are calling deprecated method").tap do |message|
  324
+      assert_match(/is deprecated and will be removed from Custom/, message)
  325
+    end
  326
+  end
  327
+
  328
+  unless defined?(::MiniTest)
2

I think this will be always defined, why do you need to test using `Test::Unit::Error in this particular case?

Steve Klabnik Collaborator

This will be, except on some distros like Fedora which (imho) give you a broken Ruby.

Especially on master, where we only support 1.9, this should basically always be true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Carlos Antonio da Silva

@LTe hey, could you please add a changelog entry for this, and check the minor comments I made, so that we can get this in master? Thanks!

Piotr Niełacny

@carlosantoniodasilva updated, rebased.

Carlos Antonio da Silva

@LTe, great thanks. I'll have to ask you one more thing though, to review your commit message and improve the changelog a bit with an example of how to use this new feature. This will help others to understand the reasoning and how to use the feature at the same time when reading the commits or the changelog.

Here's an explanation about how to go with the commit message, and here's another about changelogs.

I'll merge it afterwards. Thanks!

and others added some commits
Robert Pankowecki extend ActiveSupport::Deprecation with self, allow other objects to e…
…xtend/include it also.

test local deprecation

deprecator object

Test ActiveSupport::Deprecation when included
2c690a0
Piotr Niełacny Change ActiveSupport::Deprecation to class.
ActiveSupport::Deprecation is now a class rather than a module. You can
get instance of ActiveSupport::Deprecation calling #instance method.

  ActiveSupport::Deprecation.instance

But when you need to get new object od ActiveSupport::Deprecation you
need to just call #new.

  @instance = ActiveSupport::Deprecation.new

Since you can create a new object, you can change the version and the
name of the library where the deprecator concerned.

  ActiveSupport::Deprecation.new('2.0', 'MyGem')

If you need use another deprecator instance you can select it in the
options of deprecate method.

  deprecate :method, :deprecator => deprecator_instance

Documentation has been updated.
71993c6
Carlos Antonio da Silva

@LTe great, thank you!

Carlos Antonio da Silva carlosantoniodasilva merged commit 01ef633 into from
Carlos Antonio da Silva carlosantoniodasilva closed this
Peter Suschlik

The definition of self.deprecator should go before this deprecate call.

Fixed @ 8692db5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 2 authors.

Sep 13, 2012
Robert Pankowecki extend ActiveSupport::Deprecation with self, allow other objects to e…
…xtend/include it also.

test local deprecation

deprecator object

Test ActiveSupport::Deprecation when included
2c690a0
Piotr Niełacny Change ActiveSupport::Deprecation to class.
ActiveSupport::Deprecation is now a class rather than a module. You can
get instance of ActiveSupport::Deprecation calling #instance method.

  ActiveSupport::Deprecation.instance

But when you need to get new object od ActiveSupport::Deprecation you
need to just call #new.

  @instance = ActiveSupport::Deprecation.new

Since you can create a new object, you can change the version and the
name of the library where the deprecator concerned.

  ActiveSupport::Deprecation.new('2.0', 'MyGem')

If you need use another deprecator instance you can select it in the
options of deprecate method.

  deprecate :method, :deprecator => deprecator_instance

Documentation has been updated.
71993c6
This page is out of date. Refresh to see the latest.
32  activesupport/CHANGELOG.md
Source Rendered
... ...
@@ -1,5 +1,37 @@
1 1
 ## Rails 4.0.0 (unreleased) ##
2 2
 
  3
+*   ActiveSupport::Deprecation is now a class. It is possible to create an instance
  4
+    of deprecator. Backwards compatibility has been preserved.
  5
+
  6
+    You can choose which instance of the deprecator will be used.
  7
+
  8
+      deprecate :method_name, :deprecator => deprecator_instance
  9
+
  10
+    You can use ActiveSupport::Deprecation in your gem.
  11
+
  12
+      require 'active_support/deprecation'
  13
+      require 'active_support/core_ext/module/deprecation'
  14
+
  15
+      class MyGem
  16
+        def old_method
  17
+        end
  18
+        deprecate :old_method => :new_method, :deprecator => deprecator
  19
+
  20
+        def new_method
  21
+        end
  22
+
  23
+        def self.deprecator
  24
+          ActiveSupport::Deprecation.new('2.0', 'MyGem')
  25
+        end
  26
+      end
  27
+
  28
+      MyGem.new.old_method
  29
+
  30
+      DEPRECATION WARNING: old_method is deprecated and will be removed from MyGem 2.0
  31
+      (use new_method instead). (called from <main> at file.rb:18)
  32
+
  33
+    *Piotr Niełacny & Robert Pankowecki*
  34
+
3 35
 *   `ERB::Util.html_escape` encodes single quote as `#39`. Decimal form has better support in old browsers. *Kalys Osmonov*
4 36
 
5 37
 *   `ActiveSupport::Callbacks`: deprecate monkey patch of object callbacks.
34  activesupport/lib/active_support/core_ext/module/deprecation.rb
... ...
@@ -1,10 +1,42 @@
1 1
 require 'active_support/deprecation/method_wrappers'
2 2
 
3 3
 class Module
4  
-  # Declare that a method has been deprecated.
5 4
   #   deprecate :foo
6 5
   #   deprecate :bar => 'message'
7 6
   #   deprecate :foo, :bar, :baz => 'warning!', :qux => 'gone!'
  7
+  #
  8
+  # You can use custom deprecator instance
  9
+  #   deprecate :foo, :deprecator => MyLib::Deprecator.new
  10
+  #   deprecate :foo, :bar => "warning!", :deprecator => MyLib::Deprecator.new
  11
+  #
  12
+  # \Custom deprecators must respond to one method
  13
+  # [deprecation_warning(deprecated_method_name, message, caller_backtrace)] will be called with the deprecated
  14
+  #                                                                          method name, the message it was declared
  15
+  #                                                                          with and caller_backtrace. Implement
  16
+  #                                                                          whatever warning behavior you like here.
  17
+  #
  18
+  # Example
  19
+  #    class MyLib::Deprecator
  20
+  #
  21
+  #      def deprecation_warning(deprecated_method_name, message, caller_backtrace)
  22
+  #         message = "#{method_name} is deprecated and will be removed from MyLibrary | #{message}"
  23
+  #         Kernel.warn message
  24
+  #      end
  25
+  #
  26
+  #    end
  27
+  #
  28
+  #    module MyLib
  29
+  #      mattr_accessor :deprecator
  30
+  #      self.deprecator = Deprecator.new
  31
+  #    end
  32
+  #
  33
+  # When we deprecate method
  34
+  #    class MyLib::Bar
  35
+  #      deprecate :foo => "this is very old method", :deprecator => MyLib.deprecator
  36
+  #    end
  37
+  #
  38
+  # It will build deprecation message and invoke deprecator warning by calling
  39
+  #   MyLib.deprecator.deprecation_warning(:foo, "this is a very old method", caller)
8 40
   def deprecate(*method_names)
9 41
     ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
10 42
   end
41  activesupport/lib/active_support/deprecation.rb
... ...
@@ -1,19 +1,40 @@
1 1
 require 'active_support/core_ext/module/deprecation'
  2
+require 'active_support/deprecation/instance_delegator'
2 3
 require 'active_support/deprecation/behaviors'
3 4
 require 'active_support/deprecation/reporting'
4 5
 require 'active_support/deprecation/method_wrappers'
5 6
 require 'active_support/deprecation/proxy_wrappers'
  7
+require 'singleton'
6 8
 
7 9
 module ActiveSupport
8  
-  module Deprecation
9  
-    class << self
10  
-      # The version the deprecated behavior will be removed, by default.
11  
-      attr_accessor :deprecation_horizon
12  
-    end
13  
-    self.deprecation_horizon = '4.1'
  10
+  # \Deprecation specifies the API used by Rails to deprecate
  11
+  # methods, instance variables, objects and constants.
  12
+  # The API depends on four methods:
  13
+  #
  14
+  # * +initialize+ which expects two parameters
  15
+  #   described below;
  16
+  class Deprecation
  17
+    include Singleton
  18
+    include InstanceDelegator
  19
+    include Behavior
  20
+    include Reporting
  21
+    include MethodWrapper
  22
+
  23
+    # The version the deprecated behavior will be removed, by default.
  24
+    attr_accessor :deprecation_horizon
14 25
 
15  
-    # By default, warnings are not silenced and debugging is off.
16  
-    self.silenced = false
17  
-    self.debug = false
  26
+    # It accepts two parameters on initialization. The first is an version of library
  27
+    # and the second is an library name
  28
+    #
  29
+    # == Example
  30
+    #
  31
+    #   ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
  32
+    def initialize(deprecation_horizon = '4.1', gem_name = 'Rails')
  33
+      self.gem_name = gem_name
  34
+      self.deprecation_horizon = deprecation_horizon
  35
+      # By default, warnings are not silenced and debugging is off.
  36
+      self.silenced = false
  37
+      self.debug = false
  38
+    end
18 39
   end
19  
-end
  40
+end
58  activesupport/lib/active_support/deprecation/behaviors.rb
... ...
@@ -1,8 +1,32 @@
1 1
 require "active_support/notifications"
2 2
 
3 3
 module ActiveSupport
4  
-  module Deprecation
5  
-    class << self
  4
+  class Deprecation
  5
+    # Default warning behaviors per Rails.env.
  6
+    DEFAULT_BEHAVIORS = {
  7
+      :stderr => Proc.new { |message, callstack|
  8
+        $stderr.puts(message)
  9
+        $stderr.puts callstack.join("\n  ") if debug
  10
+      },
  11
+      :log => Proc.new { |message, callstack|
  12
+        logger =
  13
+            if defined?(Rails) && Rails.logger
  14
+              Rails.logger
  15
+            else
  16
+              require 'active_support/logger'
  17
+              ActiveSupport::Logger.new($stderr)
  18
+            end
  19
+        logger.warn message
  20
+        logger.debug callstack.join("\n  ") if debug
  21
+      },
  22
+      :notify => Proc.new { |message, callstack|
  23
+        ActiveSupport::Notifications.instrument("deprecation.rails",
  24
+                                                :message => message, :callstack => callstack)
  25
+      },
  26
+      :silence => Proc.new { |message, callstack| }
  27
+    }
  28
+
  29
+    module Behavior
6 30
       # Whether to print a backtrace along with the warning.
7 31
       attr_accessor :debug
8 32
 
@@ -16,9 +40,9 @@ def behavior
16 40
       #
17 41
       # Available behaviors:
18 42
       #
19  
-      # [+stderr+]  Log all deprecation warnings to <tt>$stderr</tt>.
  43
+      # [+stderr+]  Log all deprecation warnings to +$stderr+.
20 44
       # [+log+]     Log all deprecation warnings to +Rails.logger+.
21  
-      # [+notify+]  Use <tt>ActiveSupport::Notifications</tt> to notify +deprecation.rails+.
  45
+      # [+notify+]  Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
22 46
       # [+silence+] Do nothing.
23 47
       #
24 48
       # Setting behaviors only affects deprecations that happen after boot time.
@@ -28,36 +52,12 @@ def behavior
28 52
       #   ActiveSupport::Deprecation.behavior = :stderr
29 53
       #   ActiveSupport::Deprecation.behavior = [:stderr, :log]
30 54
       #   ActiveSupport::Deprecation.behavior = MyCustomHandler
31  
-      #   ActiveSupport::Deprecation.behavior = proc { |message, callstack| 
  55
+      #   ActiveSupport::Deprecation.behavior = proc { |message, callstack|
32 56
       #     # custom stuff
33 57
       #   }
34 58
       def behavior=(behavior)
35 59
         @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || b }
36 60
       end
37 61
     end
38  
-
39  
-    # Default warning behaviors per Rails.env.
40  
-    DEFAULT_BEHAVIORS = {
41  
-      :stderr => Proc.new { |message, callstack|
42  
-         $stderr.puts(message)
43  
-         $stderr.puts callstack.join("\n  ") if debug
44  
-       },
45  
-      :log => Proc.new { |message, callstack|
46  
-         logger =
47  
-           if defined?(Rails) && Rails.logger
48  
-             Rails.logger
49  
-           else
50  
-             require 'active_support/logger'
51  
-             ActiveSupport::Logger.new($stderr)
52  
-           end
53  
-         logger.warn message
54  
-         logger.debug callstack.join("\n  ") if debug
55  
-       },
56  
-       :notify => Proc.new { |message, callstack|
57  
-          ActiveSupport::Notifications.instrument("deprecation.rails",
58  
-          :message => message, :callstack => callstack)
59  
-       },
60  
-       :silence => Proc.new { |message, callstack| }
61  
-    }
62 62
   end
63 63
 end
24  activesupport/lib/active_support/deprecation/instance_delegator.rb
... ...
@@ -0,0 +1,24 @@
  1
+require 'active_support/core_ext/kernel/singleton_class'
  2
+require 'active_support/core_ext/module/delegation'
  3
+
  4
+module ActiveSupport
  5
+  class Deprecation
  6
+    module InstanceDelegator
  7
+      def self.included(base)
  8
+        base.extend(ClassMethods)
  9
+        base.public_class_method :new
  10
+      end
  11
+
  12
+      module ClassMethods
  13
+        def include(included_module)
  14
+          included_module.instance_methods.each { |m| method_added(m) }
  15
+          super
  16
+        end
  17
+
  18
+        def method_added(method_name)
  19
+          singleton_class.delegate(method_name, to: :instance)
  20
+        end
  21
+      end
  22
+    end
  23
+  end
  24
+end
70  activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -2,45 +2,41 @@
2 2
 require 'active_support/core_ext/array/extract_options'
3 3
 
4 4
 module ActiveSupport
5  
-  module Deprecation
6  
-    # Declare that a method has been deprecated.
7  
-    #
8  
-    #   module Fred
9  
-    #     extend self
10  
-    #
11  
-    #     def foo; end
12  
-    #     def bar; end
13  
-    #     def baz; end
14  
-    #   end
15  
-    #
16  
-    #   ActiveSupport::Deprecation.deprecate_methods(Fred, :foo, bar: :qux, baz: 'use Bar#baz instead')
17  
-    #   # => [:foo, :bar, :baz]
18  
-    #
19  
-    #   Fred.foo
20  
-    #   # => "DEPRECATION WARNING: foo is deprecated and will be removed from Rails 4.1."
21  
-    #
22  
-    #   Fred.bar
23  
-    #   # => "DEPRECATION WARNING: bar is deprecated and will be removed from Rails 4.1 (use qux instead)."
24  
-    #
25  
-    #   Fred.baz
26  
-    #   # => "DEPRECATION WARNING: baz is deprecated and will be removed from Rails 4.1 (use Bar#baz instead)."
27  
-    def self.deprecate_methods(target_module, *method_names)
28  
-      options = method_names.extract_options!
29  
-      method_names += options.keys
  5
+  class Deprecation
  6
+    module MethodWrapper
  7
+      # Declare that a method has been deprecated.
  8
+      #
  9
+      #   module Fred
  10
+      #     extend self
  11
+      #
  12
+      #     def foo; end
  13
+      #     def bar; end
  14
+      #     def baz; end
  15
+      #   end
  16
+      #
  17
+      #   ActiveSupport::Deprecation.deprecate_methods(Fred, :foo, bar: :qux, baz: 'use Bar#baz instead')
  18
+      #   # => [:foo, :bar, :baz]
  19
+      #
  20
+      #   Fred.foo
  21
+      #   # => "DEPRECATION WARNING: foo is deprecated and will be removed from Rails 4.1."
  22
+      #
  23
+      #   Fred.bar
  24
+      #   # => "DEPRECATION WARNING: bar is deprecated and will be removed from Rails 4.1 (use qux instead)."
  25
+      #
  26
+      #   Fred.baz
  27
+      #   # => "DEPRECATION WARNING: baz is deprecated and will be removed from Rails 4.1 (use Bar#baz instead)."
  28
+      def deprecate_methods(target_module, *method_names)
  29
+        options = method_names.extract_options!
  30
+        deprecator = options.delete(:deprecator) || ActiveSupport::Deprecation.instance
  31
+        method_names += options.keys
30 32
 
31  
-      method_names.each do |method_name|
32  
-        target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
33  
-          target_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
34  
-            def #{target}_with_deprecation#{punctuation}(*args, &block)
35  
-              ::ActiveSupport::Deprecation.warn(
36  
-                ::ActiveSupport::Deprecation.deprecated_method_warning(
37  
-                  :#{method_name},
38  
-                  #{options[method_name].inspect}),
39  
-                caller
40  
-              )
41  
-              send(:#{target}_without_deprecation#{punctuation}, *args, &block)
  33
+        method_names.each do |method_name|
  34
+          target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
  35
+            target_module.send(:define_method, "#{target}_with_deprecation#{punctuation}") do |*args, &block|
  36
+              deprecator.deprecation_warning(method_name, options[method_name], caller)
  37
+              send(:"#{target}_without_deprecation#{punctuation}", *args, &block)
42 38
             end
43  
-          end_eval
  39
+          end
44 40
         end
45 41
       end
46 42
     end
70  activesupport/lib/active_support/deprecation/proxy_wrappers.rb
... ...
@@ -1,7 +1,7 @@
1 1
 require 'active_support/inflector/methods'
2 2
 
3 3
 module ActiveSupport
4  
-  module Deprecation
  4
+  class Deprecation
5 5
     class DeprecationProxy #:nodoc:
6 6
       def self.new(*args, &block)
7 7
         object = args.first
@@ -25,10 +25,21 @@ def method_missing(called, *args, &block)
25 25
         end
26 26
     end
27 27
 
28  
-    class DeprecatedObjectProxy < DeprecationProxy #:nodoc:
29  
-      def initialize(object, message)
  28
+    # This DeprecatedObjectProxy transforms object to depracated object.
  29
+    #
  30
+    # Example
  31
+    #   @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!")
  32
+    # Example with custom deprecator
  33
+    #   @old_object = DeprecatedObjectProxy.new(Object.new, "Don't use this object anymore!", deprecator_instance)
  34
+    #
  35
+    # When someone execute any method expect +inspect+ on proxy object this will trigger +warn+ method on +deprecator_instance+
  36
+    #
  37
+    # Default deprecator is ActiveSupport::Deprecation
  38
+    class DeprecatedObjectProxy < DeprecationProxy
  39
+      def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
30 40
         @object = object
31 41
         @message = message
  42
+        @deprecator = deprecator
32 43
       end
33 44
 
34 45
       private
@@ -37,15 +48,38 @@ def target
37 48
         end
38 49
 
39 50
         def warn(callstack, called, args)
40  
-          ActiveSupport::Deprecation.warn(@message, callstack)
  51
+          @deprecator.warn(@message, callstack)
41 52
         end
42 53
     end
43 54
 
44  
-    # Stand-in for <tt>@request</tt>, <tt>@attributes</tt>, <tt>@params</tt>, etc.
45  
-    # which emits deprecation warnings on any method call (except +inspect+).
46  
-    class DeprecatedInstanceVariableProxy < DeprecationProxy #:nodoc:
47  
-      def initialize(instance, method, var = "@#{method}")
48  
-        @instance, @method, @var = instance, method, var
  55
+    # This DeprecatedInstanceVariableProxy transforms instance variable to depracated instance variable.
  56
+    #
  57
+    # Example
  58
+    #  class Example
  59
+    #    def initialize(deprecator)
  60
+    #      @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
  61
+    #      @_request = :a_request
  62
+    #    end
  63
+    #
  64
+    #    def request
  65
+    #       @_request
  66
+    #     end
  67
+    #
  68
+    #    def old_request
  69
+    #       @request
  70
+    #    end
  71
+    #  end
  72
+    #
  73
+    # When someone execute any method on @request variable this will trigger +warn+ method on +deprecator_instance+
  74
+    # and will fetch @_request variable via +request+ method and execute the same method on non-proxy instance variable.
  75
+    #
  76
+    # Default deprecator is ActiveSupport::Deprecation
  77
+    class DeprecatedInstanceVariableProxy < DeprecationProxy
  78
+      def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
  79
+        @instance = instance
  80
+        @method = method
  81
+        @var = var
  82
+        @deprecator = deprecator
49 83
       end
50 84
 
51 85
       private
@@ -54,14 +88,24 @@ def target
54 88
         end
55 89
 
56 90
         def warn(callstack, called, args)
57  
-          ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
  91
+          @deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
58 92
         end
59 93
     end
60 94
 
61  
-    class DeprecatedConstantProxy < DeprecationProxy #:nodoc:all
62  
-      def initialize(old_const, new_const)
  95
+    # This DeprecatedConstantProxy transforms constant to depracated constant.
  96
+    #
  97
+    # Example
  98
+    #   OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST')
  99
+    # Example with custom deprecator
  100
+    #   OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST', deprecator_instance)
  101
+    # When someone use old constant this will trigger +warn+ method on +deprecator_instance+
  102
+    #
  103
+    # Default deprecator is ActiveSupport::Deprecation
  104
+    class DeprecatedConstantProxy < DeprecationProxy
  105
+      def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance)
63 106
         @old_const = old_const
64 107
         @new_const = new_const
  108
+        @deprecator = deprecator
65 109
       end
66 110
 
67 111
       def class
@@ -74,7 +118,7 @@ def target
74 118
         end
75 119
 
76 120
         def warn(callstack, called, args)
77  
-          ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
  121
+          @deprecator.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
78 122
         end
79 123
     end
80 124
   end
32  activesupport/lib/active_support/deprecation/reporting.rb
... ...
@@ -1,7 +1,10 @@
1 1
 module ActiveSupport
2  
-  module Deprecation
3  
-    class << self
  2
+  class Deprecation
  3
+    module Reporting
  4
+      # Whether to print a message (silent mode)
4 5
       attr_accessor :silenced
  6
+      # Name of gem where method is deprecated
  7
+      attr_accessor :gem_name
5 8
 
6 9
       # Outputs a deprecation warning to the output configured by
7 10
       # <tt>ActiveSupport::Deprecation.behavior</tt>.
@@ -31,16 +34,29 @@ def silence
31 34
         @silenced = old_silenced
32 35
       end
33 36
 
34  
-      def deprecated_method_warning(method_name, message = nil)
35  
-        warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
36  
-        case message
37  
-          when Symbol then "#{warning} (use #{message} instead)"
38  
-          when String then "#{warning} (#{message})"
39  
-          else warning
  37
+      def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = caller)
  38
+        deprecated_method_warning(deprecated_method_name, message).tap do |message|
  39
+          warn(message, caller_backtrace)
40 40
         end
41 41
       end
42 42
 
43 43
       private
  44
+        # Outputs a deprecation warning message
  45
+        #   ActiveSupport::Deprecation.deprecated_method_warning(:method_name)
  46
+        #   # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon}"
  47
+        #   ActiveSupport::Deprecation.deprecated_method_warning(:method_name, :another_method)
  48
+        #   # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (use another_method instead)"
  49
+        #   ActiveSupport::Deprecation.deprecated_method_warning(:method_name, "Optional message")
  50
+        #   # => "method_name is deprecated and will be removed from Rails #{deprecation_horizon} (Optional message)"
  51
+        def deprecated_method_warning(method_name, message = nil)
  52
+          warning = "#{method_name} is deprecated and will be removed from #{gem_name} #{deprecation_horizon}"
  53
+          case message
  54
+            when Symbol then "#{warning} (use #{message} instead)"
  55
+            when String then "#{warning} (#{message})"
  56
+            else warning
  57
+          end
  58
+        end
  59
+
44 60
         def deprecation_message(callstack, message = nil)
45 61
           message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
46 62
           message += '.' unless message =~ /\.$/
149  activesupport/test/deprecation_test.rb
@@ -104,6 +104,17 @@ def test_default_stderr_behavior
104 104
     assert_match(/call stack!/, content)
105 105
   end
106 106
 
  107
+  def test_default_stderr_behavior_with_warn_method
  108
+    ActiveSupport::Deprecation.behavior = :stderr
  109
+
  110
+    content = capture(:stderr) {
  111
+      ActiveSupport::Deprecation.warn('Instance error!', ['instance call stack!'])
  112
+    }
  113
+
  114
+    assert_match(/Instance error!/, content)
  115
+    assert_match(/instance call stack!/, content)
  116
+  end
  117
+
107 118
   def test_default_silence_behavior
108 119
     ActiveSupport::Deprecation.behavior = :silence
109 120
     behavior = ActiveSupport::Deprecation.behavior.first
@@ -186,4 +197,142 @@ def test_deprecation_with_alternate_method
186 197
   def test_deprecation_with_explicit_message
187 198
     assert_deprecated(/you now need to do something extra for this one/) { @dtc.d }
188 199
   end
  200
+
  201
+  def test_deprecation_in_other_object
  202
+    messages = []
  203
+
  204
+    klass = Class.new do
  205
+      delegate :warn, :behavior=, to: ActiveSupport::Deprecation
  206
+    end
  207
+
  208
+    o = klass.new
  209
+    o.behavior = Proc.new { |message, callstack| messages << message }
  210
+    assert_difference("messages.size") do
  211
+      o.warn("warning")
  212
+    end
  213
+  end
  214
+
  215
+  def test_deprecated_method_with_custom_method_warning
  216
+    deprecator = deprecator_with_messages
  217
+
  218
+    class << deprecator
  219
+      private
  220
+        def deprecated_method_warning(method, message)
  221
+          "deprecator.deprecated_method_warning.#{method}"
  222
+        end
  223
+    end
  224
+
  225
+    deprecatee = Class.new do
  226
+      def method
  227
+      end
  228
+      deprecate :method, deprecator: deprecator
  229
+    end
  230
+
  231
+    deprecatee.new.method
  232
+    assert deprecator.messages.first.match("DEPRECATION WARNING: deprecator.deprecated_method_warning.method")
  233
+  end
  234
+
  235
+  def test_deprecate_with_custom_deprecator
  236
+    custom_deprecator = mock('Deprecator') do
  237
+      expects(:deprecation_warning)
  238
+    end
  239
+
  240
+    klass = Class.new do
  241
+      def method
  242
+      end
  243
+      deprecate :method, deprecator: custom_deprecator
  244
+    end
  245
+
  246
+    klass.new.method
  247
+  end
  248
+
  249
+  def test_deprecated_constant_with_deprecator_given
  250
+    deprecator = deprecator_with_messages
  251
+    klass = Class.new
  252
+    klass.const_set(:OLD, ActiveSupport::Deprecation::DeprecatedConstantProxy.new('klass::OLD', 'Object', deprecator) )
  253
+    assert_difference("deprecator.messages.size") do
  254
+      klass::OLD.to_s
  255
+    end
  256
+  end
  257
+  
  258
+  def test_deprecated_instance_variable_with_instance_deprecator
  259
+    deprecator = deprecator_with_messages
  260
+    
  261
+    klass = Class.new() do
  262
+      def initialize(deprecator)
  263
+        @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
  264
+        @_request = :a_request
  265
+      end
  266
+      def request; @_request end
  267
+      def old_request; @request end
  268
+    end
  269
+
  270
+    assert_difference("deprecator.messages.size") { klass.new(deprecator).old_request.to_s }
  271
+  end
  272
+
  273
+  def test_deprecated_instance_variable_with_given_deprecator
  274
+    deprecator = deprecator_with_messages
  275
+
  276
+    klass = Class.new do
  277
+      define_method(:initialize) do
  278
+        @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
  279
+        @_request = :a_request
  280
+      end
  281
+      def request; @_request end
  282
+      def old_request; @request end
  283
+    end
  284
+
  285
+    assert_difference("deprecator.messages.size") { klass.new.old_request.to_s }
  286
+  end
  287
+
  288
+  def test_delegate_deprecator_instance
  289
+    klass = Class.new do
  290
+      attr_reader :last_message
  291
+      delegate :warn, :behavior=, to: ActiveSupport::Deprecation
  292
+
  293
+      def initialize
  294
+        self.behavior = [Proc.new { |message| @last_message = message }]
  295
+      end
  296
+
  297
+      def deprecated_method
  298
+        warn(deprecated_method_warning(:deprecated_method, "You are calling deprecated method"))
  299
+      end
  300
+
  301
+      private
  302
+        def deprecated_method_warning(method_name, message = nil)
  303
+          message || "#{method_name} is deprecated and will be removed from This Library"
  304
+        end
  305
+    end
  306
+
  307
+    object = klass.new
  308
+    object.deprecated_method
  309
+    assert_match(/You are calling deprecated method/, object.last_message)
  310
+  end
  311
+
  312
+  def test_default_gem_name
  313
+    deprecator = ActiveSupport::Deprecation.new
  314
+
  315
+    deprecator.send(:deprecated_method_warning, :deprecated_method, "You are calling deprecated method").tap do |message|
  316
+      assert_match(/is deprecated and will be removed from Rails/, message)
  317
+    end
  318
+  end
  319
+
  320
+  def test_custom_gem_name
  321
+    deprecator = ActiveSupport::Deprecation.new('2.0', 'Custom')
  322
+
  323
+    deprecator.send(:deprecated_method_warning, :deprecated_method, "You are calling deprecated method").tap do |message|
  324
+      assert_match(/is deprecated and will be removed from Custom/, message)
  325
+    end
  326
+  end
  327
+
  328
+  private
  329
+    def deprecator_with_messages
  330
+      klass = Class.new(ActiveSupport::Deprecation)
  331
+      deprecator = klass.new
  332
+      deprecator.behavior = Proc.new{|message, callstack| deprecator.messages << message}
  333
+      def deprecator.messages
  334
+        @messages ||= []
  335
+      end
  336
+      deprecator
  337
+    end
189 338
 end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.