1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Ruby 1.9.2: disallow explicit coercion via method_missing. Only give friendly nil errors for Array and Active Record methods.

This commit is contained in:
Jeremy Kemper 2009-11-13 12:15:49 -08:00
parent 0214d337b3
commit 9acc824d96
4 changed files with 35 additions and 19 deletions

View file

@ -1,7 +1,9 @@
class NameError
# Extract the name of the missing constant from the exception message.
def missing_name
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
if /undefined local variable or method/ !~ message
$1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
end
end
# Was this exception raised because the given name was missing?

View file

@ -43,7 +43,14 @@ class NilClass
private
def method_missing(method, *args, &block)
raise_nil_warning_for METHOD_CLASS_MAP[method], method, caller
# Ruby 1.9.2: disallow explicit coercion via method_missing.
if method == :to_ary || method == :to_str
super
elsif klass = METHOD_CLASS_MAP[method]
raise_nil_warning_for klass, method, caller
else
super
end
end
# Raises a NoMethodError when you attempt to call a method on +nil+.
@ -55,4 +62,3 @@ class NilClass
raise NoMethodError, message, with_caller || caller
end
end

View file

@ -3,23 +3,19 @@ require 'active_support/core_ext/name_error'
class NameErrorTest < Test::Unit::TestCase
def test_name_error_should_set_missing_name
begin
SomeNameThatNobodyWillUse____Really ? 1 : 0
flunk "?!?!"
rescue NameError => exc
assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name
assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really)
assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really")
end
SomeNameThatNobodyWillUse____Really ? 1 : 0
flunk "?!?!"
rescue NameError => exc
assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name
assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really)
assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really")
end
def test_missing_method_should_ignore_missing_name
begin
some_method_that_does_not_exist
flunk "?!?!"
rescue NameError => exc
assert_equal nil, exc.missing_name
assert ! exc.missing_name?(:Foo)
end
some_method_that_does_not_exist
flunk "?!?!"
rescue NameError => exc
assert !exc.missing_name?(:Foo)
assert_nil exc.missing_name
end
end

View file

@ -13,7 +13,7 @@ class WhinyNilTest < Test::Unit::TestCase
def test_unchanged
nil.method_thats_not_in_whiners
rescue NoMethodError => nme
assert_match(/nil.method_thats_not_in_whiners/, nme.message)
assert(nme.message =~ /nil:NilClass/)
end
def test_active_record
@ -35,4 +35,16 @@ class WhinyNilTest < Test::Unit::TestCase
rescue RuntimeError => nme
assert(!(nme.message =~ /nil:NilClass/))
end
def test_no_to_ary_coercion
nil.to_ary
rescue NoMethodError => nme
assert(nme.message =~ /nil:NilClass/)
end
def test_no_to_str_coercion
nil.to_str
rescue NoMethodError => nme
assert(nme.message =~ /nil:NilClass/)
end
end