* An alternative exception is passed as option, eg. default tip
authorHenryk Gerlach <hg@littleimpact.de>
Wed Sep 03 13:29:54 2008 +0200 (2008-09-03)
changeset 319ab433e33b9
parent 2 b7d1f129ccc9
* An alternative exception is passed as option, eg.
s.constantzie_with_care(Lst,CustomException)
becomes
s.constantzie_with_care(Lst, :exception => CustomException)
* support for :ancestors option
CHANGELOG
MIT-LICENSE
README
lib/constantize_with_care.rb
test/constantize_with_care_test.rb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/CHANGELOG	Wed Sep 03 13:29:54 2008 +0200
     1.3 @@ -0,0 +1,5 @@
     1.4 + * An alternative exception is passed as option, eg 
     1.5 +     s.constantzie_with_care(Lst,CustomException) 
     1.6 +   becomes 
     1.7 +     s.constantzie_with_care(Lst, :exception =>  CustomException)
     1.8 + * support for :ancestors option
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/MIT-LICENSE	Wed Sep 03 13:29:54 2008 +0200
     2.3 @@ -0,0 +1,20 @@
     2.4 +Copyright (c) 2008 Henryk Gerlach
     2.5 +
     2.6 +Permission is hereby granted, free of charge, to any person obtaining
     2.7 +a copy of this software and associated documentation files (the
     2.8 +"Software"), to deal in the Software without restriction, including
     2.9 +without limitation the rights to use, copy, modify, merge, publish,
    2.10 +distribute, sublicense, and/or sell copies of the Software, and to
    2.11 +permit persons to whom the Software is furnished to do so, subject to
    2.12 +the following conditions:
    2.13 +
    2.14 +The above copyright notice and this permission notice shall be
    2.15 +included in all copies or substantial portions of the Software.
    2.16 +
    2.17 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    2.18 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    2.19 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    2.20 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    2.21 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    2.22 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    2.23 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     3.1 --- a/README	Sun Aug 10 16:21:57 2008 +0200
     3.2 +++ b/README	Wed Sep 03 13:29:54 2008 +0200
     3.3 @@ -2,7 +2,7 @@
     3.4  
     3.5  == License
     3.6  Copyright (c) 2008 Henryk Gerach, released under the MIT license
     3.7 -see lib/constantize_with_care.rb
     3.8 +see MIT-LICENSE
     3.9  
    3.10  == Homepage
    3.11  http://www.littleimpact.de/hg/constantize_with_care/
    3.12 @@ -17,7 +17,7 @@
    3.13  (disrecommended since difficult).
    3.14  
    3.15  If the string is not allowed to be constantized an exception is raised.
    3.16 -The +exception+ defaults to RuntimeError and can be overidden.
    3.17 +The +exception+ defaults to RuntimeError and can be overidden in the options.
    3.18  
    3.19  The method <tt>constantize_with_care</tt> is added to the String class.
    3.20  Instead of <tt>String#constantize</tt> the method 
    3.21 @@ -35,7 +35,7 @@
    3.22  
    3.23    # For the lazy
    3.24    "String".constantize_with_care([String,Fixnum])           #=> String
    3.25 -  "Float".constantize_with_care([String,Fixnum], Exception) #=> raises Exception
    3.26 +  "Float".constantize_with_care([String,Fixnum], :exception => Exception) #=> raises Exception
    3.27  
    3.28    # For the daring
    3.29    # Everything that starts with S is okay:
     4.1 --- a/lib/constantize_with_care.rb	Sun Aug 10 16:21:57 2008 +0200
     4.2 +++ b/lib/constantize_with_care.rb	Wed Sep 03 13:29:54 2008 +0200
     4.3 @@ -1,31 +1,34 @@
     4.4  # Copyright (c) 2008 Henryk Gerlach
     4.5 -#
     4.6 -# Permission is hereby granted, free of charge, to any person obtaining
     4.7 -# a copy of this software and associated documentation files (the
     4.8 -# "Software"), to deal in the Software without restriction, including
     4.9 -# without limitation the rights to use, copy, modify, merge, publish,
    4.10 -# distribute, sublicense, and/or sell copies of the Software, and to
    4.11 -# permit persons to whom the Software is furnished to do so, subject to
    4.12 -# the following conditions:
    4.13 -#
    4.14 -# The above copyright notice and this permission notice shall be
    4.15 -# included in all copies or substantial portions of the Software.
    4.16 -#
    4.17 -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    4.18 -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    4.19 -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    4.20 -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    4.21 -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    4.22 -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    4.23 -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    4.24 +# see MIT-LICENSE
    4.25  module ConstantizeWithCare
    4.26 -  def constantize_with_care(allowed_classes, exception="I'm not allowed to constantize \`#{self}'!")
    4.27 +  def self.included(includer)
    4.28 +    includer.class_eval do
    4.29 +      alias :constantize_really_trusted_data :constantize
    4.30 +    end
    4.31 +  end
    4.32 +
    4.33 +  # Constantizes the string after checking whether it is allowed to be constantized.
    4.34 +  #
    4.35 +  # Options are:
    4.36 +  # * <tt>:exception</tt> - the exception that should be raised if the string is forbidden (defaults to <tt>RuntimeError</tt>)
    4.37 +  # * <tt>:ancestors</tt> - <tt>self</tt> may be constantized even if any of its superclasses is contained in <tt>allowed_classes</tt> (defaults to <tt>false</tt>)
    4.38 +  def constantize_with_care(allowed_classes, options ={}) 
    4.39 +    options.reverse_merge!({:exception => "I'm not allowed to constantize \`#{self}'!"})
    4.40      ok = false
    4.41 -    if allowed_classes.respond_to? :include? and allowed_classes.include?(self)
    4.42 +    if options[:ancestors]
    4.43 +      self_class = self.constantize
    4.44 +      if allowed_classes.respond_to? :intersection \
    4.45 +         and allowed_classes.intersection(self_class.ancestors.map(&:to_s))
    4.46 +           ok = true
    4.47 +      end
    4.48 +      if not ok and (allowed_classes.map(&:to_s) & self_class.ancestors.map(&:to_s)).size > 0
    4.49 +        ok = true
    4.50 +      end
    4.51 +    elsif allowed_classes.respond_to? :include? and allowed_classes.include?(self)
    4.52        ok = true
    4.53 -    elsif not ok and allowed_classes.is_a? Regexp and allowed_classes =~ self
    4.54 +    elsif allowed_classes.is_a? Regexp and allowed_classes =~ self
    4.55        ok = true
    4.56 -    elsif not ok and allowed_classes.respond_to? :each
    4.57 +    elsif allowed_classes.respond_to? :each
    4.58        allowed_classes.each do |klass|
    4.59          if self == klass.to_s
    4.60            ok = true
    4.61 @@ -33,11 +36,7 @@
    4.62          end
    4.63        end
    4.64      end
    4.65 -    raise exception unless ok
    4.66 -    self.constantize
    4.67 -  end
    4.68 - 
    4.69 -  def constantize_really_trusted_data
    4.70 +    raise options[:exception] unless ok
    4.71      self.constantize
    4.72    end
    4.73  end
     5.1 --- a/test/constantize_with_care_test.rb	Sun Aug 10 16:21:57 2008 +0200
     5.2 +++ b/test/constantize_with_care_test.rb	Wed Sep 03 13:29:54 2008 +0200
     5.3 @@ -21,11 +21,21 @@
     5.4  require "#{File.dirname(__FILE__)}/../lib/constantize_with_care"
     5.5  String.send :include, ConstantizeWithCare
     5.6  
     5.7 +class MyException < Exception
     5.8 +end
     5.9 +
    5.10 +class MyParent
    5.11 +end
    5.12 +  
    5.13 +class MyKlass < MyParent
    5.14 +end
    5.15 +
    5.16 +class MyChild < MyKlass
    5.17 +end
    5.18 +
    5.19 +
    5.20 +
    5.21  class ConstantizeWithCareTest< Test::Unit::TestCase
    5.22 -
    5.23 -  class MyException < Exception
    5.24 -  end
    5.25 -
    5.26    def test_default_exception
    5.27      e = assert_raise(RuntimeError) {
    5.28        "Float".constantize_with_care(["String","Fixnum"])
    5.29 @@ -35,7 +45,7 @@
    5.30  
    5.31    def test_exception_override
    5.32      assert_raise(MyException) {
    5.33 -      "Float".constantize_with_care(["String","Fixnum"], MyException)
    5.34 +      "Float".constantize_with_care(["String","Fixnum"], :exception => MyException)
    5.35      }
    5.36    end
    5.37  
    5.38 @@ -72,4 +82,12 @@
    5.39    def test_constantize_really_trusted_data
    5.40      assert_equal String, "String".constantize_really_trusted_data
    5.41    end
    5.42 +
    5.43 +  def test_ancestors
    5.44 +    assert_equal "MyKlass".constantize_with_care(["MyParent", "MyException"], :ancestors => true), MyKlass
    5.45 +    assert_equal "MyKlass".constantize_with_care([MyParent, MyException], :ancestors => true), MyKlass
    5.46 +    assert_raise(RuntimeError) {
    5.47 +      "MyKlass".constantize_with_care([MyChild,MyException], :ancestors => true)
    5.48 +    }
    5.49 +  end
    5.50  end