mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Revert all the stuff to do with disallowing non-public methods for Module#delegate
This commit is contained in:
parent
bad6803570
commit
8ba491acc3
7 changed files with 3 additions and 194 deletions
|
@ -2,8 +2,6 @@
|
|||
|
||||
* Added Array#prepend as an alias for Array#unshift and Array#append as an alias for Array#<< [DHH]
|
||||
|
||||
* Removed support for using Module#delegate to delegate to non-public methods [Jon Leighton]
|
||||
|
||||
* The definition of blank string for Ruby 1.9 has been extended to Unicode whitespace.
|
||||
Also, in 1.8 the ideographic space U+3000 is considered to be whitespace. [Akira Matsuda, Damien Mathieu]
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
require 'active_support/core_ext/object/public_send'
|
||||
require 'active_support/core_ext/string/starts_ends_with'
|
||||
|
||||
class Module
|
||||
# Provides a delegate class method to easily expose contained objects' methods
|
||||
# as your own. Pass one or more methods (specified as symbols or strings)
|
||||
|
@ -127,13 +124,12 @@ class Module
|
|||
|
||||
methods.each do |method|
|
||||
method = method.to_s
|
||||
call = method.ends_with?('=') ? "public_send(:#{method}, " : "#{method}("
|
||||
|
||||
if allow_nil
|
||||
module_eval(<<-EOS, file, line - 2)
|
||||
def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
|
||||
if #{to} || #{to}.respond_to?(:#{method}) # if client || client.respond_to?(:name)
|
||||
#{to}.#{call}*args, &block) # client.name(*args, &block)
|
||||
#{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
|
||||
end # end
|
||||
end # end
|
||||
EOS
|
||||
|
@ -142,7 +138,7 @@ class Module
|
|||
|
||||
module_eval(<<-EOS, file, line - 1)
|
||||
def #{method_prefix}#{method}(*args, &block) # def customer_name(*args, &block)
|
||||
#{to}.#{call}*args, &block) # client.name(*args, &block)
|
||||
#{to}.__send__(:#{method}, *args, &block) # client.__send__(:name, *args, &block)
|
||||
rescue NoMethodError # rescue NoMethodError
|
||||
if #{to}.nil? # if client.nil?
|
||||
#{exception} # # add helpful message to the exception
|
||||
|
|
|
@ -3,7 +3,6 @@ require 'active_support/core_ext/object/blank'
|
|||
require 'active_support/core_ext/object/duplicable'
|
||||
require 'active_support/core_ext/object/try'
|
||||
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/instance_variables'
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
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)
|
||||
# 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
|
|
@ -28,20 +28,10 @@ end
|
|||
|
||||
Somewhere = Struct.new(:street, :city) do
|
||||
attr_accessor :name
|
||||
|
||||
protected
|
||||
|
||||
def protected_method
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def private_method
|
||||
end
|
||||
end
|
||||
|
||||
class Someone < Struct.new(:name, :place)
|
||||
delegate :street, :city, :to_f, :protected_method, :private_method, :to => :place
|
||||
delegate :street, :city, :to_f, :to => :place
|
||||
delegate :name=, :to => :place, :prefix => true
|
||||
delegate :upcase, :to => "place.city"
|
||||
|
||||
|
@ -93,14 +83,6 @@ class ModuleTest < Test::Unit::TestCase
|
|||
assert_equal "Fred", @david.place.name
|
||||
end
|
||||
|
||||
def test_delegation_to_protected_method
|
||||
assert_raise(NoMethodError) { @david.protected_method }
|
||||
end
|
||||
|
||||
def test_delegation_to_private_method
|
||||
assert_raise(NoMethodError) { @david.private_method }
|
||||
end
|
||||
|
||||
def test_delegation_down_hierarchy
|
||||
assert_equal "CHICAGO", @david.upcase
|
||||
end
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
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
|
|
@ -452,30 +452,6 @@ Examples of +in?+:
|
|||
|
||||
NOTE: Defined in +active_support/core_ext/object/inclusion.rb+.
|
||||
|
||||
h4. +public_send+
|
||||
|
||||
This method is available by default in Ruby 1.9, and is backported to Ruby 1.8 by Active Support. Like the regular +send+ method, +public_send+ allows you to call a method when the name is not known until runtime. However, if the method is not public then a +NoMethodError+ exception will be raised.
|
||||
|
||||
<ruby>
|
||||
class Greeter
|
||||
def hello(who)
|
||||
"Hello " + who
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def secret
|
||||
"sauce"
|
||||
end
|
||||
end
|
||||
|
||||
greeter = Greeter.new
|
||||
greeter.public_send(:hello, 'Jim') # => "Hello Jim"
|
||||
greeter.public_send(:secret) # => NoMethodError
|
||||
</ruby>
|
||||
|
||||
NOTE: Defined in +active_support/core_ext/object/public_send.rb+.
|
||||
|
||||
h3. Extensions to +Module+
|
||||
|
||||
h4. +alias_method_chain+
|
||||
|
|
Loading…
Reference in a new issue