Froze rails gems
[depot.git] / vendor / rails / activesupport / lib / active_support / deprecation.rb
1 require 'yaml'
2
3 module ActiveSupport
4 module Deprecation #:nodoc:
5 mattr_accessor :debug
6 self.debug = false
7
8 # Choose the default warn behavior according to RAILS_ENV.
9 # Ignore deprecation warnings in production.
10 DEFAULT_BEHAVIORS = {
11 'test' => Proc.new { |message, callstack|
12 $stderr.puts(message)
13 $stderr.puts callstack.join("\n ") if debug
14 },
15 'development' => Proc.new { |message, callstack|
16 logger = defined?(::RAILS_DEFAULT_LOGGER) ? ::RAILS_DEFAULT_LOGGER : Logger.new($stderr)
17 logger.warn message
18 logger.debug callstack.join("\n ") if debug
19 }
20 }
21
22 class << self
23 def warn(message = nil, callstack = caller)
24 behavior.call(deprecation_message(callstack, message), callstack) if behavior && !silenced?
25 end
26
27 def default_behavior
28 if defined?(RAILS_ENV)
29 DEFAULT_BEHAVIORS[RAILS_ENV.to_s]
30 else
31 DEFAULT_BEHAVIORS['test']
32 end
33 end
34
35 # Have deprecations been silenced?
36 def silenced?
37 @silenced = false unless defined?(@silenced)
38 @silenced
39 end
40
41 # Silence deprecation warnings within the block.
42 def silence
43 old_silenced, @silenced = @silenced, true
44 yield
45 ensure
46 @silenced = old_silenced
47 end
48
49 attr_writer :silenced
50
51
52 private
53 def deprecation_message(callstack, message = nil)
54 message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
55 "DEPRECATION WARNING: #{message}. #{deprecation_caller_message(callstack)}"
56 end
57
58 def deprecation_caller_message(callstack)
59 file, line, method = extract_callstack(callstack)
60 if file
61 if line && method
62 "(called from #{method} at #{file}:#{line})"
63 else
64 "(called from #{file}:#{line})"
65 end
66 end
67 end
68
69 def extract_callstack(callstack)
70 if md = callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
71 md.captures
72 else
73 callstack.first
74 end
75 end
76 end
77
78 # Behavior is a block that takes a message argument.
79 mattr_accessor :behavior
80 self.behavior = default_behavior
81
82 # Warnings are not silenced by default.
83 self.silenced = false
84
85 module ClassMethods #:nodoc:
86 # Declare that a method has been deprecated.
87 def deprecate(*method_names)
88 options = method_names.extract_options!
89 method_names = method_names + options.keys
90 method_names.each do |method_name|
91 alias_method_chain(method_name, :deprecation) do |target, punctuation|
92 class_eval(<<-EOS, __FILE__, __LINE__)
93 def #{target}_with_deprecation#{punctuation}(*args, &block)
94 ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:#{method_name}, #{options[method_name].inspect}), caller)
95 #{target}_without_deprecation#{punctuation}(*args, &block)
96 end
97 EOS
98 end
99 end
100 end
101
102 def deprecated_method_warning(method_name, message=nil)
103 warning = "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
104 case message
105 when Symbol then "#{warning} (use #{message} instead)"
106 when String then "#{warning} (#{message})"
107 else warning
108 end
109 end
110
111 def deprecation_horizon
112 '2.3'
113 end
114 end
115
116 module Assertions #:nodoc:
117 def assert_deprecated(match = nil, &block)
118 result, warnings = collect_deprecations(&block)
119 assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
120 if match
121 match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
122 assert warnings.any? { |w| w =~ match }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
123 end
124 result
125 end
126
127 def assert_not_deprecated(&block)
128 result, deprecations = collect_deprecations(&block)
129 assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
130 result
131 end
132
133 private
134 def collect_deprecations
135 old_behavior = ActiveSupport::Deprecation.behavior
136 deprecations = []
137 ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
138 deprecations << message
139 end
140 result = yield
141 [result, deprecations]
142 ensure
143 ActiveSupport::Deprecation.behavior = old_behavior
144 end
145 end
146
147 class DeprecationProxy #:nodoc:
148 silence_warnings do
149 instance_methods.each { |m| undef_method m unless m =~ /^__/ }
150 end
151
152 # Don't give a deprecation warning on inspect since test/unit and error
153 # logs rely on it for diagnostics.
154 def inspect
155 target.inspect
156 end
157
158 private
159 def method_missing(called, *args, &block)
160 warn caller, called, args
161 target.__send__(called, *args, &block)
162 end
163 end
164
165 class DeprecatedObjectProxy < DeprecationProxy
166 def initialize(object, message)
167 @object = object
168 @message = message
169 end
170
171 private
172 def target
173 @object
174 end
175
176 def warn(callstack, called, args)
177 ActiveSupport::Deprecation.warn(@message, callstack)
178 end
179 end
180
181 # Stand-in for <tt>@request</tt>, <tt>@attributes</tt>, <tt>@params</tt>, etc.
182 # which emits deprecation warnings on any method call (except +inspect+).
183 class DeprecatedInstanceVariableProxy < DeprecationProxy #:nodoc:
184 def initialize(instance, method, var = "@#{method}")
185 @instance, @method, @var = instance, method, var
186 end
187
188 private
189 def target
190 @instance.__send__(@method)
191 end
192
193 def warn(callstack, called, args)
194 ActiveSupport::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack)
195 end
196 end
197
198 class DeprecatedConstantProxy < DeprecationProxy #:nodoc:
199 def initialize(old_const, new_const)
200 @old_const = old_const
201 @new_const = new_const
202 end
203
204 def class
205 target.class
206 end
207
208 private
209 def target
210 @new_const.to_s.constantize
211 end
212
213 def warn(callstack, called, args)
214 ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
215 end
216 end
217 end
218 end
219
220 class Module
221 include ActiveSupport::Deprecation::ClassMethods
222 end
223
224 require 'test/unit/error'
225
226 module Test
227 module Unit
228 class TestCase
229 include ActiveSupport::Deprecation::Assertions
230 end
231
232 class Error # :nodoc:
233 # Silence warnings when reporting test errors.
234 def message_with_silenced_deprecation
235 ActiveSupport::Deprecation.silence do
236 message_without_silenced_deprecation
237 end
238 end
239
240 alias_method_chain :message, :silenced_deprecation
241 end
242 end
243 end