From 7d017781393b72a5257dbbfc99b124a7a0c492f1 Mon Sep 17 00:00:00 2001 From: Jeremy Kemper Date: Tue, 1 Aug 2006 11:12:38 +0000 Subject: 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. Test prints to , dev logs, production ignores. git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4647 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activesupport/CHANGELOG | 5 ++ activesupport/lib/active_support/deprecation.rb | 106 +++++++++++++++------- activesupport/test/deprecation_test.rb | 115 ++++++++++-------------- 3 files changed, 124 insertions(+), 102 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 01b1e6d7b9..98aa5b4468 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -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] diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb index a72b12bcfe..77c00f5a67 100644 --- a/activesupport/lib/active_support/deprecation.rb +++ b/activesupport/lib/active_support/deprecation.rb @@ -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 diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb index c691b5bde0..5fb0c5b042 100644 --- a/activesupport/test/deprecation_test.rb +++ b/activesupport/test/deprecation_test.rb @@ -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 -- cgit v1.2.3