mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Backport Object#public_send to 1.8 so that we can implement Module#delegate such that non-public methods raise
This commit is contained in:
parent
652ab436db
commit
6f4b405250
3 changed files with 143 additions and 0 deletions
|
@ -3,6 +3,7 @@ require 'active_support/core_ext/object/blank'
|
||||||
require 'active_support/core_ext/object/duplicable'
|
require 'active_support/core_ext/object/duplicable'
|
||||||
require 'active_support/core_ext/object/try'
|
require 'active_support/core_ext/object/try'
|
||||||
require 'active_support/core_ext/object/inclusion'
|
require 'active_support/core_ext/object/inclusion'
|
||||||
|
require 'active_support/core_ext/object/public_send'
|
||||||
|
|
||||||
require 'active_support/core_ext/object/conversions'
|
require 'active_support/core_ext/object/conversions'
|
||||||
require 'active_support/core_ext/object/instance_variables'
|
require 'active_support/core_ext/object/instance_variables'
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
require 'active_support/core_ext/kernel/singleton_class'
|
||||||
|
|
||||||
|
class Object
|
||||||
|
unless Object.public_method_defined?(:public_send)
|
||||||
|
# Backports Object#public_send from 1.9
|
||||||
|
def public_send(method, *args, &block) # :nodoc:
|
||||||
|
# Don't create a singleton class for the object if it doesn't already have one
|
||||||
|
# (This also protects us from classes like Fixnum and Symbol, which cannot have a
|
||||||
|
# singleton class.)
|
||||||
|
klass = singleton_methods.any? ? self.singleton_class : self.class
|
||||||
|
|
||||||
|
if klass.public_method_defined?(method)
|
||||||
|
send(method, *args, &block)
|
||||||
|
else
|
||||||
|
if klass.private_method_defined?(method)
|
||||||
|
raise NoMethodError, "private method `#{method}' called for #{inspect}"
|
||||||
|
elsif klass.protected_method_defined?(method)
|
||||||
|
raise NoMethodError, "protected method `#{method}' called for #{inspect}"
|
||||||
|
else
|
||||||
|
raise NoMethodError, "undefined method `#{method}' for #{inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
117
activesupport/test/core_ext/object/public_send_test.rb
Normal file
117
activesupport/test/core_ext/object/public_send_test.rb
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
require 'abstract_unit'
|
||||||
|
require 'active_support/core_ext/object/public_send'
|
||||||
|
|
||||||
|
module PublicSendReceiver
|
||||||
|
def receive_public_method(*args)
|
||||||
|
return args + [yield]
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def receive_protected_method(*args)
|
||||||
|
return args + [yield]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def receive_private_method(*args)
|
||||||
|
return args + [yield]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Note, running this on 1.9 will be testing the Ruby core implementation, but it is good to
|
||||||
|
# do this to ensure that our backport functions the same as Ruby core in 1.9
|
||||||
|
class PublicSendTest < Test::Unit::TestCase
|
||||||
|
def instance
|
||||||
|
@instance ||= begin
|
||||||
|
klass = Class.new do
|
||||||
|
include PublicSendReceiver
|
||||||
|
end
|
||||||
|
klass.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def singleton_instance
|
||||||
|
@singleton_instance ||= begin
|
||||||
|
object = Object.new
|
||||||
|
object.singleton_class.send(:include, PublicSendReceiver)
|
||||||
|
object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_receive_public_method
|
||||||
|
assert_equal(
|
||||||
|
[:foo, :bar, :baz],
|
||||||
|
instance.public_send(:receive_public_method, :foo, :bar) { :baz }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_receive_public_singleton_method
|
||||||
|
assert_equal(
|
||||||
|
[:foo, :bar, :baz],
|
||||||
|
singleton_instance.public_send(:receive_public_method, :foo, :bar) { :baz }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_on_protected_method
|
||||||
|
assert_raises(NoMethodError) do
|
||||||
|
instance.public_send(:receive_protected_method, :foo, :bar) { :baz }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_on_protected_singleton_method
|
||||||
|
assert_raises(NoMethodError) do
|
||||||
|
singleton_instance.public_send(:receive_protected_method, :foo, :bar) { :baz }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_on_private_method
|
||||||
|
assert_raises(NoMethodError) do
|
||||||
|
instance.public_send(:receive_private_method, :foo, :bar) { :baz }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_on_singleton_private_method
|
||||||
|
assert_raises(NoMethodError) do
|
||||||
|
singleton_instance.public_send(:receive_private_method, :foo, :bar) { :baz }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_on_undefined_method
|
||||||
|
assert_raises(NoMethodError) do
|
||||||
|
instance.public_send(:receive_undefined_method, :foo, :bar) { :baz }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_protected_method_message
|
||||||
|
instance.public_send(:receive_protected_method, :foo, :bar) { :baz }
|
||||||
|
rescue NoMethodError => exception
|
||||||
|
assert_equal(
|
||||||
|
"protected method `receive_protected_method' called for #{instance.inspect}",
|
||||||
|
exception.message
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_private_method_message
|
||||||
|
instance.public_send(:receive_private_method, :foo, :bar) { :baz }
|
||||||
|
rescue NoMethodError => exception
|
||||||
|
assert_equal(
|
||||||
|
"private method `receive_private_method' called for #{instance.inspect}",
|
||||||
|
exception.message
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_undefined_method_message
|
||||||
|
instance.public_send(:receive_undefined_method, :foo, :bar) { :baz }
|
||||||
|
rescue NoMethodError => exception
|
||||||
|
assert_equal(
|
||||||
|
"undefined method `receive_undefined_method' for #{instance.inspect}",
|
||||||
|
exception.message
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_receiver_with_no_singleton
|
||||||
|
assert_equal "5", 5.public_send(:to_s)
|
||||||
|
assert_equal "foo", :foo.public_send(:to_s)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue