Permalink
Browse files

Deprecation: easier to work with warning behavior as procs; default b…

…ehaviors for each environment so users needn't update env.rb; and testing pleasure with assert_deprecated, assert_not_deprecated. Test prints to , dev logs, production ignores.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4647 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent 4f017bb commit 7d017781393b72a5257dbbfc99b124a7a0c492f1 @jeremy jeremy committed Aug 1, 2006
Showing with 124 additions and 102 deletions.
  1. +5 −0 activesupport/CHANGELOG
  2. +74 −32 activesupport/lib/active_support/deprecation.rb
  3. +45 −70 activesupport/test/deprecation_test.rb
@@ -1,5 +1,10 @@
*SVN*
+* Deprecation: easier to work with warning behavior as procs; default behaviors for each environment so users needn't update env.rb; and testing pleasure with assert_deprecated, assert_not_deprecated. [Jeremy Kemper]
+ By default, test prints to $stderr, dev logs, production ignores.
+ Provide your own per-environment in e.g. config/environments/development.rb:
+ ActiveSupport::Deprecation.behavior = Proc.new { |message| raise message }
+
* First cut of the Rails Deprecation system. [Koz]
* Strip boolean XML content before checking for 'true' [Rick Olson]
@@ -1,46 +1,88 @@
module ActiveSupport
module Deprecation
- @@warning_method = :print
- mattr_accessor :warning_method
-
+ # Choose the default warn behavior according to RAILS_ENV.
+ # Ignore deprecation warnings in production.
+ DEFAULT_BEHAVIORS = {
+ 'test' => Proc.new { |message| $stderr.puts message },
+ 'development' => Proc.new { |message| RAILS_DEFAULT_LOGGER.warn message },
+ }
+
class << self
+ def warn(message = nil, callstack = caller)
+ behavior.call(deprecation_message(callstack, message)) if behavior
+ end
- def print_warning(lines)
- lines.each {|l| $stderr.write("#{l}\n")}
+ def default_behavior
+ DEFAULT_BEHAVIORS[RAILS_ENV.to_s] if defined?(RAILS_ENV)
end
-
- def log_warning(lines)
- if Object.const_defined?("RAILS_DEFAULT_LOGGER")
- lines.each {|l| RAILS_DEFAULT_LOGGER.warn l}
- else
- print_warning(lines)
+
+ private
+ def deprecation_message(callstack, message = nil)
+ file, line, method = extract_callstack(callstack)
+ message ||= "WARNING: #{method} is deprecated and will be removed from the next Rails release"
+ "#{message} (#{method} at #{file}:#{line})"
+ end
+
+ def extract_callstack(callstack)
+ callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures
end
- end
-
- def issue_warning(line)
- lines =
- ["@@@@@@@@@@ Deprecation Warning @@@@@@@@@@", line,
- "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"]
- self.send("#{@@warning_method}_warning", lines)
- end
-
- def instance_method_warning(clazz, method)
- issue_warning("Your application calls #{clazz}##{method}, which is now deprecated. Please see the API documents at http://api.rubyonrails.org/ for more information.")
- end
end
-
+
+ # Behavior is a block that takes a message argument.
+ mattr_accessor :behavior
+ self.behavior = default_behavior
+
module ClassMethods
- def deprecate(method_name)
- alias_method "#{method_name}_before_deprecation", method_name
- class_eval(<<-EOS, __FILE__, __LINE__)
- def #{method_name}(*args)
- ::ActiveSupport::Deprecation.instance_method_warning(self.class, :#{method_name})
- #{method_name}_before_deprecation *args
+ # Declare that a method has been deprecated.
+ def deprecate(*method_names)
+ method_names.each do |method_name|
+ class_eval(<<-EOS, __FILE__, __LINE__)
+ def #{method_name}_with_deprecation(*args, &block)
+ ::ActiveSupport::Deprecation.warn
+ #{method_name}_without_deprecation(*args, &block)
+ end
+ EOS
+ alias_method_chain(method_name, :deprecation)
end
- EOS
end
end
+
+ module Assertions
+ def assert_deprecated(regexp = nil, &block)
+ last = with_last_message_tracking_deprecation_behavior(&block)
+ assert last, "Expected a deprecation warning within the block but received none"
+ if regexp
+ assert_match regexp, last, "Deprecation warning didn't match #{regexp}: #{last}"
+ end
+ end
+
+ def assert_not_deprecated(&block)
+ last = with_last_message_tracking_deprecation_behavior(&block)
+ assert_nil last, "Expected no deprecation warning within the block but received one: #{last}"
+ end
+
+ private
+ def with_last_message_tracking_deprecation_behavior
+ old_behavior = ActiveSupport::Deprecation.behavior
+ last_message = nil
+ ActiveSupport::Deprecation.behavior = Proc.new { |message| last_message = message; old_behavior.call(message) if old_behavior }
+ yield
+ last_message
+ ensure
+ ActiveSupport::Deprecation.behavior = old_behavior
+ end
+ end
end
end
-Object.extend(ActiveSupport::Deprecation::ClassMethods)
+class Class
+ include ActiveSupport::Deprecation::ClassMethods
+end
+
+module Test
+ module Unit
+ class TestCase
+ include ActiveSupport::Deprecation::Assertions
+ end
+ end
+end
@@ -1,85 +1,60 @@
-require 'test/unit'
-require File.dirname(__FILE__) + '/../lib/active_support/deprecation'
+require File.dirname(__FILE__) + '/abstract_unit'
-# Stub out the warnings to allow assertions
-module ActiveSupport
- module Deprecation
- class << self
- def issue_warning(message)
- @@warning = message
- end
- def last_warning
- @@warning
- end
- end
+class Deprecatee
+ def partially(foo = nil)
+ ActiveSupport::Deprecation.warn 'calling with foo=nil is out' if foo.nil?
end
-end
-
-class DeprecationTestingClass
- def partiallly_deprecated(foo = nil)
- if foo.nil?
- ActiveSupport::Deprecation.issue_warning("calling partially_deprecated with foo=nil is now deprecated")
- end
- end
-
- def not_deprecated
- 2
- end
-
- def deprecated_no_args
- 1
- end
- deprecate :deprecated_no_args
-
- def deprecated_one_arg(a)
- a
- end
- deprecate :deprecated_one_arg
-
- def deprecated_multiple_args(a,b,c)
- [a,b,c]
- end
- deprecate :deprecated_multiple_args
-
+ def not() 2 end
+ def none() 1 end
+ def one(a) a end
+ def multi(a,b,c) [a,b,c] end
+ deprecate :none, :one, :multi
end
class DeprecationTest < Test::Unit::TestCase
def setup
- @dtc = DeprecationTestingClass.new
- ActiveSupport::Deprecation.issue_warning(nil) # reset
- end
-
- def test_partial_deprecation
- @dtc.partiallly_deprecated
- assert_warning_matches /foo=nil/
- end
-
- def test_raises_nothing
- assert_equal 2, @dtc.not_deprecated
+ # Track the last warning.
+ @old_behavior = ActiveSupport::Deprecation.behavior
+ @last_message = nil
+ ActiveSupport::Deprecation.behavior = Proc.new { |message| @last_message = message }
+
+ @dtc = Deprecatee.new
end
-
- def test_deprecating_class_method
- assert_equal 1, @dtc.deprecated_no_args
- assert_deprecation_warning
- assert_warning_matches /DeprecationTestingClass#deprecated_no_args/
+
+ def teardown
+ ActiveSupport::Deprecation.behavior = @old_behavior
end
-
- def test_deprecating_class_method_with_argument
- assert_equal 1, @dtc.deprecated_one_arg(1)
+
+ def test_inline_deprecation_warning
+ assert_deprecated(/foo=nil/) do
+ @dtc.partially
+ end
end
-
- def test_deprecating_class_method_with_argument
- assert_equal [1,2,3], @dtc.deprecated_multiple_args(1,2,3)
+
+ def test_undeprecated
+ assert_not_deprecated do
+ assert_equal 2, @dtc.not
+ end
end
-
- private
- def assert_warning_matches(rx)
- assert ActiveSupport::Deprecation.last_warning =~ rx, "The deprecation warning did not match #{rx}"
+
+ def test_deprecate_class_method
+ assert_deprecated(/none is deprecated/) do
+ assert_equal 1, @dtc.none
+ end
+
+ assert_deprecated(/one is deprecated/) do
+ assert_equal 1, @dtc.one(1)
+ end
+
+ assert_deprecated(/multi is deprecated/) do
+ assert_equal [1,2,3], @dtc.multi(1,2,3)
+ end
end
-
- def assert_deprecation_warning
- assert_not_nil ActiveSupport::Deprecation.last_warning, "No Deprecation warnings were issued"
+
+ def test_nil_behavior_is_ignored
+ ActiveSupport::Deprecation.behavior = nil
+ assert_deprecated(/foo=nil/) { @dtc.partially }
end
end

0 comments on commit 7d01778

Please sign in to comment.