[前][次][番号順一覧][スレッド一覧]

ruby-changes:31905

From: nobu <ko1@a...>
Date: Wed, 4 Dec 2013 12:48:05 +0900 (JST)
Subject: [ruby-changes:31905] nobu:r43984 (trunk): delegate.rb: ignore unset target

nobu	2013-12-04 12:47:57 +0900 (Wed, 04 Dec 2013)

  New Revision: 43984

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43984

  Log:
    delegate.rb: ignore unset target
    
    * lib/delegate.rb (Delegator#method_missing): ignore the target if not
      set, and delegate to global methods.  [ruby-core:58572] [Bug #9155]
    * lib/delegate.rb (Delegator#respond_to_missing): ditto.
    * lib/delegate.rb (SimpleDelegator#__getobj__): yield and return if
      not delegated but a block is given, like as Hash#fetch.
    * lib/delegate.rb (DelegateClass#__getobj__): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/lib/delegate.rb
    trunk/test/test_delegate.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43983)
+++ ChangeLog	(revision 43984)
@@ -1,3 +1,15 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Dec  4 12:47:54 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* lib/delegate.rb (Delegator#method_missing): ignore the target if not
+	  set, and delegate to global methods.  [ruby-core:58572] [Bug #9155]
+
+	* lib/delegate.rb (Delegator#respond_to_missing): ditto.
+
+	* lib/delegate.rb (SimpleDelegator#__getobj__): yield and return if
+	  not delegated but a block is given, like as Hash#fetch.
+
+	* lib/delegate.rb (DelegateClass#__getobj__): ditto.
+
 Tue Dec  3 23:48:18 2013  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in: check malloc_size() available on BSD.
Index: lib/delegate.rb
===================================================================
--- lib/delegate.rb	(revision 43983)
+++ lib/delegate.rb	(revision 43984)
@@ -74,9 +74,10 @@ class Delegator < BasicObject https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L74
   # Handles the magic of delegation through \_\_getobj\_\_.
   #
   def method_missing(m, *args, &block)
-    target = self.__getobj__
+    r = true
+    target = self.__getobj__ {r = false}
     begin
-      if target.respond_to?(m)
+      if r && target.respond_to?(m)
         target.__send__(m, *args, &block)
       elsif ::Kernel.respond_to?(m, true)
         ::Kernel.instance_method(m).bind(self).(*args, &block)
@@ -93,8 +94,10 @@ class Delegator < BasicObject https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L94
   # call through \_\_getobj\_\_.
   #
   def respond_to_missing?(m, include_private)
-    r = self.__getobj__.respond_to?(m, include_private)
-    if r && include_private && !self.__getobj__.respond_to?(m, false)
+    r = true
+    target = self.__getobj__ {r = false}
+    r &&= target.respond_to?(m, include_private)
+    if r && include_private && !target.respond_to?(m, false)
       warn "#{caller(3)[0]}: delegator does not forward private method \##{m}"
       return false
     end
@@ -306,7 +309,10 @@ end https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L309
 class SimpleDelegator<Delegator
   # Returns the current object method calls are being delegated to.
   def __getobj__
-    __raise__ ::ArgumentError, "not delegated" unless defined?(@delegate_sd_obj)
+    unless defined?(@delegate_sd_obj)
+      return yield if block_given?
+      __raise__ ::ArgumentError, "not delegated"
+    end
     @delegate_sd_obj
   end
 
@@ -381,7 +387,10 @@ def DelegateClass(superclass) https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L387
   methods -= [:to_s,:inspect,:=~,:!~,:===]
   klass.module_eval do
     def __getobj__  # :nodoc:
-      __raise__ ::ArgumentError, "not delegated" unless defined?(@delegate_dc_obj)
+      unless defined?(@delegate_dc_obj)
+        return yield if block_given?
+        __raise__ ::ArgumentError, "not delegated"
+      end
       @delegate_dc_obj
     end
     def __setobj__(obj)  # :nodoc:
Index: test/test_delegate.rb
===================================================================
--- test/test_delegate.rb	(revision 43983)
+++ test/test_delegate.rb	(revision 43984)
@@ -168,4 +168,16 @@ class TestDelegateClass < Test::Unit::Te https://github.com/ruby/ruby/blob/trunk/test/test_delegate.rb#L168
       d.__getobj__
     }
   end
+
+  class Bug9155 < DelegateClass(Integer)
+    def initialize(value)
+      super(Integer(value))
+    end
+  end
+
+  def test_global_method_if_no_target
+    bug9155 = '[ruby-core:58572] [Bug #9155]'
+    x = assert_nothing_raised(ArgumentError, bug9155) {break Bug9155.new(1)}
+    assert_equal(1, x.to_i, bug9155)
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]