Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 4647

Show
Ignore:
Timestamp:
08/01/06 11:12:38 (2 years ago)
Author:
bitsweat
Message:

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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activesupport/CHANGELOG

    r4623 r4647  
    11*SVN* 
     2 
     3* 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] 
     4  By default, test prints to $stderr, dev logs, production ignores. 
     5  Provide your own per-environment in e.g. config/environments/development.rb: 
     6    ActiveSupport::Deprecation.behavior = Proc.new { |message| raise message } 
    27 
    38* First cut of the Rails Deprecation system.   [Koz] 
  • trunk/activesupport/lib/active_support/deprecation.rb

    r4623 r4647  
    11module ActiveSupport 
    22  module Deprecation 
    3     @@warning_method = :print 
    4     mattr_accessor :warning_method 
    5      
     3    # Choose the default warn behavior according to RAILS_ENV. 
     4    # Ignore deprecation warnings in production. 
     5    DEFAULT_BEHAVIORS = { 
     6      'test'        => Proc.new { |message| $stderr.puts message }, 
     7      'development' => Proc.new { |message| RAILS_DEFAULT_LOGGER.warn message }, 
     8    } 
     9 
    610    class << self 
     11      def warn(message = nil, callstack = caller) 
     12        behavior.call(deprecation_message(callstack, message)) if behavior 
     13      end 
    714 
    8       def print_warning(lines) 
    9         lines.each {|l| $stderr.write("#{l}\n")} 
     15      def default_behavior 
     16        DEFAULT_BEHAVIORS[RAILS_ENV.to_s] if defined?(RAILS_ENV) 
    1017      end 
    11        
    12       def log_warning(lines) 
    13         if Object.const_defined?("RAILS_DEFAULT_LOGGER") 
    14           lines.each {|l| RAILS_DEFAULT_LOGGER.warn l} 
    15         else 
    16           print_warning(lines) 
     18 
     19      private 
     20        def deprecation_message(callstack, message = nil) 
     21          file, line, method = extract_callstack(callstack) 
     22          message ||= "WARNING: #{method} is deprecated and will be removed from the next Rails release" 
     23          "#{message} (#{method} at #{file}:#{line})" 
     24        end 
     25 
     26        def extract_callstack(callstack) 
     27          callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures 
     28        end 
     29    end 
     30 
     31    # Behavior is a block that takes a message argument. 
     32    mattr_accessor :behavior 
     33    self.behavior = default_behavior 
     34 
     35    module ClassMethods 
     36      # Declare that a method has been deprecated. 
     37      def deprecate(*method_names) 
     38        method_names.each do |method_name| 
     39          class_eval(<<-EOS, __FILE__, __LINE__) 
     40            def #{method_name}_with_deprecation(*args, &block) 
     41              ::ActiveSupport::Deprecation.warn 
     42              #{method_name}_without_deprecation(*args, &block) 
     43            end 
     44          EOS 
     45          alias_method_chain(method_name, :deprecation) 
    1746        end 
    1847      end 
    19        
    20       def issue_warning(line) 
    21         lines =  
    22         ["@@@@@@@@@@ Deprecation Warning @@@@@@@@@@", line, 
    23          "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"] 
    24         self.send("#{@@warning_method}_warning", lines) 
     48    end 
     49 
     50    module Assertions 
     51      def assert_deprecated(regexp = nil, &block) 
     52        last = with_last_message_tracking_deprecation_behavior(&block) 
     53        assert last, "Expected a deprecation warning within the block but received none" 
     54        if regexp 
     55          assert_match regexp, last, "Deprecation warning didn't match #{regexp}: #{last}" 
     56        end 
    2557      end 
    26        
    27       def instance_method_warning(clazz, method) 
    28         issue_warning("Your application calls #{clazz}##{method}, which is now deprecated.  Please see the API documents at http://api.rubyonrails.org/ for more information.") 
     58 
     59      def assert_not_deprecated(&block) 
     60        last = with_last_message_tracking_deprecation_behavior(&block) 
     61        assert_nil last, "Expected no deprecation warning within the block but received one: #{last}" 
    2962      end 
    30     end 
    31      
    32     module ClassMethods 
    33       def deprecate(method_name) 
    34         alias_method "#{method_name}_before_deprecation", method_name 
    35         class_eval(<<-EOS, __FILE__, __LINE__) 
    36         def #{method_name}(*args) 
    37           ::ActiveSupport::Deprecation.instance_method_warning(self.class, :#{method_name}) 
    38           #{method_name}_before_deprecation *args 
     63 
     64      private 
     65        def with_last_message_tracking_deprecation_behavior 
     66          old_behavior = ActiveSupport::Deprecation.behavior 
     67          last_message = nil 
     68          ActiveSupport::Deprecation.behavior = Proc.new { |message| last_message = message; old_behavior.call(message) if old_behavior } 
     69          yield 
     70          last_message 
     71        ensure 
     72          ActiveSupport::Deprecation.behavior = old_behavior 
    3973        end 
    40         EOS 
    41       end 
    4274    end 
    4375  end 
    4476end 
    4577 
    46 Object.extend(ActiveSupport::Deprecation::ClassMethods) 
     78class Class 
     79  include ActiveSupport::Deprecation::ClassMethods 
     80end 
     81 
     82module Test 
     83  module Unit 
     84    class TestCase 
     85      include ActiveSupport::Deprecation::Assertions 
     86    end 
     87  end 
     88end 
  • trunk/activesupport/test/deprecation_test.rb

    r4623 r4647  
    1 require 'test/unit' 
    2 require File.dirname(__FILE__) + '/../lib/active_support/deprecation' 
     1require File.dirname(__FILE__) + '/abstract_unit' 
    32 
    4 # Stub out the warnings to allow assertions 
    5 module ActiveSupport 
    6   module Deprecation 
    7     class << self 
    8       def issue_warning(message) 
    9         @@warning = message 
    10       end 
    11       def last_warning 
    12         @@warning 
    13       end 
    14     end 
     3class Deprecatee 
     4  def partially(foo = nil) 
     5    ActiveSupport::Deprecation.warn 'calling with foo=nil is out' if foo.nil? 
    156  end 
    16 end 
    177 
    18 class DeprecationTestingClass 
    19  
    20   def partiallly_deprecated(foo = nil) 
    21     if foo.nil? 
    22       ActiveSupport::Deprecation.issue_warning("calling partially_deprecated with foo=nil is now deprecated") 
    23     end 
    24   end 
    25    
    26   def not_deprecated 
    27     2 
    28   end 
    29    
    30   def deprecated_no_args 
    31     1 
    32   end 
    33   deprecate :deprecated_no_args 
    34    
    35   def deprecated_one_arg(a) 
    36     a 
    37   end 
    38   deprecate :deprecated_one_arg 
    39    
    40   def deprecated_multiple_args(a,b,c) 
    41     [a,b,c] 
    42   end 
    43   deprecate :deprecated_multiple_args 
    44    
     8  def not() 2 end 
     9  def none() 1 end 
     10  def one(a) a end 
     11  def multi(a,b,c) [a,b,c] end 
     12  deprecate :none, :one, :multi 
    4513end 
    4614 
     
    4816class DeprecationTest < Test::Unit::TestCase 
    4917  def setup 
    50     @dtc = DeprecationTestingClass.new 
    51     ActiveSupport::Deprecation.issue_warning(nil) # reset 
     18    # Track the last warning. 
     19    @old_behavior = ActiveSupport::Deprecation.behavior 
     20    @last_message = nil 
     21    ActiveSupport::Deprecation.behavior = Proc.new { |message| @last_message = message } 
     22 
     23    @dtc = Deprecatee.new 
    5224  end 
    53    
    54   def test_partial_deprecation 
    55     @dtc.partiallly_deprecated 
    56     assert_warning_matches /foo=nil/ 
     25 
     26  def teardown 
     27    ActiveSupport::Deprecation.behavior = @old_behavior 
    5728  end 
    58    
    59   def test_raises_nothing 
    60     assert_equal 2, @dtc.not_deprecated 
     29 
     30  def test_inline_deprecation_warning 
     31    assert_deprecated(/foo=nil/) do 
     32      @dtc.partially 
     33    end 
    6134  end 
    62    
    63   def test_deprecating_class_metho
    64     assert_equal 1, @dtc.deprecated_no_args 
    65     assert_deprecation_warning 
    66     assert_warning_matches /DeprecationTestingClass#deprecated_no_args/ 
     35 
     36  def test_undeprecate
     37    assert_not_deprecated do 
     38      assert_equal 2, @dtc.not 
     39    end 
    6740  end 
    68    
    69   def test_deprecating_class_method_with_argument 
    70     assert_equal 1, @dtc.deprecated_one_arg(1) 
     41 
     42  def test_deprecate_class_method 
     43    assert_deprecated(/none is deprecated/) do 
     44      assert_equal 1, @dtc.none 
     45    end 
     46 
     47    assert_deprecated(/one is deprecated/) do 
     48      assert_equal 1, @dtc.one(1) 
     49    end 
     50 
     51    assert_deprecated(/multi is deprecated/) do 
     52      assert_equal [1,2,3], @dtc.multi(1,2,3) 
     53    end 
    7154  end 
    72    
    73   def test_deprecating_class_method_with_argument 
    74     assert_equal [1,2,3], @dtc.deprecated_multiple_args(1,2,3) 
    75   end 
    76    
    77   private 
    78   def assert_warning_matches(rx) 
    79     assert ActiveSupport::Deprecation.last_warning =~ rx, "The deprecation warning did not match #{rx}" 
    80   end 
    81    
    82   def assert_deprecation_warning 
    83     assert_not_nil ActiveSupport::Deprecation.last_warning, "No Deprecation warnings were issued" 
     55 
     56  def test_nil_behavior_is_ignored 
     57    ActiveSupport::Deprecation.behavior = nil 
     58    assert_deprecated(/foo=nil/) { @dtc.partially } 
    8459  end 
    8560end