4 module Deprecation
#:nodoc:
8 # Choose the default warn behavior according to RAILS_ENV.
9 # Ignore deprecation warnings in production.
11 'test' => Proc
.new
{ |message
, callstack
|
13 $stderr.puts callstack
.join("\n ") if debug
15 'development' => Proc
.new
{ |message
, callstack
|
16 logger
= defined?(::RAILS_DEFAULT_LOGGER) ? ::RAILS_DEFAULT_LOGGER : Logger
.new($stderr)
18 logger
.debug callstack
.join("\n ") if debug
23 def warn(message
= nil, callstack
= caller
)
24 behavior
.call(deprecation_message(callstack
, message
), callstack
) if behavior
&& !silenced
?
28 if defined?(RAILS_ENV
)
29 DEFAULT_BEHAVIORS
[RAILS_ENV
.to_s
]
31 DEFAULT_BEHAVIORS
['test']
35 # Have deprecations been silenced?
37 @silenced = false unless defined?(@silenced)
41 # Silence deprecation warnings within the block.
43 old_silenced
, @silenced = @silenced, true
46 @silenced = old_silenced
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)}"
58 def deprecation_caller_message(callstack
)
59 file
, line
, method
= extract_callstack(callstack
)
62 "(called from #{method} at #{file}:#{line})"
64 "(called from #{file}:#{line})"
69 def extract_callstack(callstack
)
70 if md
= callstack
.first
.match(/^(.+?):(\d+)(?::in `(.*?)')?/)
78 # Behavior is a block that takes a message argument.
79 mattr_accessor
:behavior
80 self.behavior
= default_behavior
82 # Warnings are not silenced by default.
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)
102 def deprecated_method_warning(method_name
, message
=nil)
103 warning
= "#{method_name} is deprecated and will be removed from Rails #{deprecation_horizon}"
105 when Symbol
then "#{warning} (use #{message} instead)"
106 when String
then "#{warning} (#{message})"
111 def deprecation_horizon
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"
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(', ')}"
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 "}"
134 def collect_deprecations
135 old_behavior
= ActiveSupport
::Deprecation.behavior
137 ActiveSupport
::Deprecation.behavior
= Proc
.new
do |message
, callstack
|
138 deprecations
<< message
141 [result
, deprecations
]
143 ActiveSupport
::Deprecation.behavior
= old_behavior
147 class DeprecationProxy
#:nodoc:
149 instance_methods
.each
{ |m
| undef_method m
unless m
=~
/^__/ }
152 # Don't give a deprecation warning on inspect since test/unit and error
153 # logs rely on it for diagnostics.
159 def method_missing(called
, *args
, &block
)
160 warn caller
, called
, args
161 target
.__send__(called
, *args
, &block
)
165 class DeprecatedObjectProxy
< DeprecationProxy
166 def initialize(object
, message
)
176 def warn(callstack
, called
, args
)
177 ActiveSupport
::Deprecation.warn(@message, callstack
)
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
190 @instance.__send__(@method)
193 def warn(callstack
, called
, args
)
194 ActiveSupport
::Deprecation.warn("#{@var} is deprecated! Call #{@method}.#{called} instead of #{@var}.#{called}. Args: #{args.inspect}", callstack
)
198 class DeprecatedConstantProxy
< DeprecationProxy
#:nodoc:
199 def initialize(old_const
, new_const
)
200 @old_const = old_const
201 @new_const = new_const
210 @new_const.to_s
.constantize
213 def warn(callstack
, called
, args
)
214 ActiveSupport
::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack
)
221 include ActiveSupport
::Deprecation::ClassMethods
224 require 'test/unit/error'
229 include ActiveSupport
::Deprecation::Assertions
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
240 alias_method_chain
:message, :silenced_deprecation