public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
lifo (author)
Tue May 13 02:39:45 -0700 2008
commit  2270371f5dbabdd25ffcc59389249a795ba324a1
tree    2f03fe4fbc3b6128e918a3f1ed62efc40088452d
parent  593e21d6aedcc05d744be4996bd7180edce57efe
rails / activesupport / lib / active_support / deprecation.rb
100644 206 lines (174 sloc) 6.472 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
require 'yaml'
 
module ActiveSupport
  module Deprecation #:nodoc:
    mattr_accessor :debug
    self.debug = false
 
    # Choose the default warn behavior according to RAILS_ENV.
    # Ignore deprecation warnings in production.
    DEFAULT_BEHAVIORS = {
      'test' => Proc.new { |message, callstack|
                         $stderr.puts(message)
                         $stderr.puts callstack.join("\n ") if debug
                       },
      'development' => Proc.new { |message, callstack|
                         logger = defined?(::RAILS_DEFAULT_LOGGER) ? ::RAILS_DEFAULT_LOGGER : Logger.new($stderr)
                         logger.warn message
                         logger.debug callstack.join("\n ") if debug
                       }
    }
 
    class << self
      def warn(message = nil, callstack = caller)
        behavior.call(deprecation_message(callstack, message), callstack) if behavior && !silenced?
      end
 
      def default_behavior
        if defined?(RAILS_ENV)
          DEFAULT_BEHAVIORS[RAILS_ENV.to_s]
        else
          DEFAULT_BEHAVIORS['test']
        end
      end
 
      # Have deprecations been silenced?
      def silenced?
        @silenced = false unless defined?(@silenced)
        @silenced
      end
 
      # Silence deprecation warnings within the block.
      def silence
        old_silenced, @silenced = @silenced, true
        yield
      ensure
        @silenced = old_silenced
      end
 
      attr_writer :silenced
 
 
      private
        def deprecation_message(callstack, message = nil)
          message ||= "You are using deprecated behavior which will be removed from Rails 2.0."
          "DEPRECATION WARNING: #{message} See http://www.rubyonrails.org/deprecation for details. #{deprecation_caller_message(callstack)}"
        end
 
        def deprecation_caller_message(callstack)
          file, line, method = extract_callstack(callstack)
          if file
            if line && method
              "(called from #{method} at #{file}:#{line})"
            else
              "(called from #{file}:#{line})"
            end
          end
        end
 
        def extract_callstack(callstack)
          if md = callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
            md.captures
          else
            callstack.first
          end
        end
    end
 
    # Behavior is a block that takes a message argument.
    mattr_accessor :behavior
    self.behavior = default_behavior
 
    # Warnings are not silenced by default.
    self.silenced = false
 
    module ClassMethods #:nodoc:
      # Declare that a method has been deprecated.
      def deprecate(*method_names)
        options = method_names.extract_options!
        method_names = method_names + options.keys
        method_names.each do |method_name|
          alias_method_chain(method_name, :deprecation) do |target, punctuation|
            class_eval(<<-EOS, __FILE__, __LINE__)
def #{target}_with_deprecation#{punctuation}(*args, &block)
::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), caller)
#{target}_without_deprecation#{punctuation}(*args, &block)
end
EOS
          end
        end
      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
        end
      end
 
      def deprecation_horizon
        '2.0'
      end
    end
 
    module Assertions #:nodoc:
      def assert_deprecated(match = nil, &block)
        result, warnings = collect_deprecations(&block)
        assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
        if match
          match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
          assert warnings.any? { |w| w =~ match }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
        end
        result
      end
 
      def assert_not_deprecated(&block)
        result, deprecations = collect_deprecations(&block)
        assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
        result
      end
 
      private
        def collect_deprecations
          old_behavior = ActiveSupport::Deprecation.behavior
          deprecations = []
          ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
            deprecations << message
          end
          result = yield
          [result, deprecations]
        ensure
          ActiveSupport::Deprecation.behavior = old_behavior
        end
    end
 
    # Stand-in for @request, @attributes, @params, etc which emits deprecation
    # warnings on any method call (except #inspect).
    class DeprecatedInstanceVariableProxy #:nodoc:
      silence_warnings do
        instance_methods.each { |m| undef_method m unless m =~ /^__/ }
      end
 
      def initialize(instance, method, var = "@#{method}")
        @instance, @method, @var = instance, method, var
      end
 
      # 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
 
        def target
          @instance.__send__(@method)
        end
 
        def warn(callstack, called, args)
          ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
        end
    end
 
  end
end
 
class Module
  include ActiveSupport::Deprecation::ClassMethods
end
 
require 'test/unit/error'
 
module Test
  module Unit
    class TestCase
      include ActiveSupport::Deprecation::Assertions
    end
 
    class Error # :nodoc:
      # Silence warnings when reporting test errors.
      def message_with_silenced_deprecation
        ActiveSupport::Deprecation.silence do
          message_without_silenced_deprecation
        end
      end
 
      alias_method_chain :message, :silenced_deprecation
    end
  end
end