proxy_wrappers.rb 4.9 KB
Newer Older
1
require 'active_support/inflector/methods'
2

3
module ActiveSupport
4
  class Deprecation
5
    class DeprecationProxy #:nodoc:
6 7
      def self.new(*args, &block)
        object = args.first
A
Aaron Patterson 已提交
8

9 10 11
        return object unless object
        super
      end
A
Aaron Patterson 已提交
12

J
Jeremy Kemper 已提交
13
      instance_methods.each { |m| undef_method m unless m =~ /^__|^object_id$/ }
14 15 16 17 18 19 20 21 22 23 24 25 26 27

      # Don't give a deprecation warning on inspect since test/unit and error
      # logs rely on it for diagnostics.
      def inspect
        target.inspect
      end

      private
        def method_missing(called, *args, &block)
          warn caller, called, args
          target.__send__(called, *args, &block)
        end
    end

28 29 30
    # DeprecatedObjectProxy transforms an object into a deprecated object. It takes an object,
    # a deprecation message, and optionally a deprecator. The deprecator defaults to
    # <tt>ActiveSupport::Deprecator</tt> if none is specified.
31
    #
32 33
    #   deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
    #   # => <Object:0x007fb9b34c34b0>
34
    #
35 36 37 38
    #   deprecated_object.to_s
    #   DEPRECATION WARNING: This object is now deprecated.
    #   (Backtrace)
    #   # => "<Object:0x007fb9b34c34b0>"
39 40
    class DeprecatedObjectProxy < DeprecationProxy
      def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
41 42
        @object = object
        @message = message
43
        @deprecator = deprecator
44 45 46 47 48 49 50 51
      end

      private
        def target
          @object
        end

        def warn(callstack, called, args)
52
          @deprecator.warn(@message, callstack)
53 54 55
        end
    end

56 57 58 59
    # DeprecatedInstanceVariableProxy transforms an instance variable into a deprecated
    # instance variable. It takes an instance of a class, a method on that class, and an
    # instance variable. It optionally takes a deprecator as the last argument. The deprecator
    # defaults to <tt>ActiveSupport::Deprecator</tt> if none is specified.
60
    #
61
    #   class Example
62
    #     def initialize
63
    #       @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
64
    #       @_request = :special_request
65
    #     end
66
    #
67
    #     def request
68 69 70
    #       @_request
    #     end
    #
71
    #     def old_request
72
    #       @request
73 74
    #     end
    #   end
75
    #
76 77 78 79 80 81 82 83
    #   example = Example.new
    #   # => #<Example:0x007fb9b31090b8 @_request=:special_request, @request=:special_request>
    #
    #   example.old_request.to_s
    #   # => DEPRECATION WARNING: @request is deprecated! Call request.to_s instead of
    #      @request.to_s
    #      (Bactrace information…)
    #      "special_request"
84
    #
85 86
    #   example.request.to_s
    #   # => "special_request"
87 88
    class DeprecatedInstanceVariableProxy < DeprecationProxy
      def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
89 90 91
        @instance = instance
        @method = method
        @var = var
92
        @deprecator = deprecator
93 94 95 96 97 98 99 100
      end

      private
        def target
          @instance.__send__(@method)
        end

        def warn(callstack, called, args)
101
          @deprecator.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
102 103 104
        end
    end

105 106 107 108 109 110
    # DeprecatedConstantProxy transforms a constant into a deprecated constant. It takes the names of an old
    # (deprecated) constant and a new contstant (both in string form), and optionally a deprecator. The
    # deprecator defaults to <tt>ActiveSupport::Deprecator</tt> if none is specified. The deprecated constant
    # now returns the return value of the new constant.
    #
    #   PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
111
    #
112
    #   (In a later update, the orignal implementation of `PLANETS` has been removed.)
113
    #
114 115
    #   PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
    #   PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
116
    #
117 118 119 120
    #   PLANETS.map { |planet| planet.capitalize }
    #   # => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
    #        (Bactrace information…)
    #        ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
121 122
    class DeprecatedConstantProxy < DeprecationProxy
      def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance)
123 124
        @old_const = old_const
        @new_const = new_const
125
        @deprecator = deprecator
126 127 128 129 130 131 132 133
      end

      def class
        target.class
      end

      private
        def target
134
          ActiveSupport::Inflector.constantize(@new_const.to_s)
135 136 137
        end

        def warn(callstack, called, args)
138
          @deprecator.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
139 140 141 142
        end
    end
  end
end