Project

General

Profile

Bug #4994

DelegateClass don't find extern global public method in 1.9.2

Added by sylvain303 (Sylvain Viart) over 8 years ago. Updated over 8 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
ruby -v:
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]
Backport:
[ruby-core:37864]

Description

How to reproduce:

require 'delegate'
require 'pp'

def test_that?(str)
str.size > 0
end

class String2 < DelegateClass(String)
def initialize(*param)
@s = String.new(*param)
super(@s)
end

def dummy
    test_that?(@s)
end

end

s2 = String2.new("pipo")

pp s2.dummy

The code above works under 1.9.1 and 1.8 but not under 1.9.2

  • ruby1.9.1 -v => ruby 1.9.1p378 (2010-01-10 revision 26273) [x86_64-linux]
  • ruby1.8 -v => ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
  • ruby -v => ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]

error message:

!ruby draft/tdelegate.rb
draft/tdelegate.rb:15:in dummy': undefined methodtest_that?' for "pipo":String2 (NoMethodError)
from draft/tdelegate.rb:21:in `'

shell returned 1

History

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Status changed from Open to Rejected

It's a spec change for [ruby-dev:39154].

  • Delegator now tries to forward all methods as possible,
  • but not for private methods, and
  • test_that? is a private method.

Probably, it would need a way to tell how the method is called in method_missing.

Updated by sylvain303 (Sylvain Viart) over 8 years ago

Sorry, but links are in Japanese.
I can read the code, but not why the DelegateClass shouldn't search the toplevel method, any more?

Could you translate or post a link to an English doc?

For the correction you suggest, I've wrote this code:
I don't like this usage as a Delegation. May be I missed something.

Edited: Wrong solution, for this method_missing() see comment after

require 'delegate'
require 'pp'

def test_that?(str)
str.size > 0
end

class String2 < DelegateClass(String)
def initialize(*param)
@s = String.new(*param)
super(@s)
end

def dummy
    test_that?(@s)
    # this method is really missing
    bla()
end

def method_missing(m, *args, &block)
    begin
        Object.send(m, *args, &block)
    rescue NameError =>e
        # doesn't work with NoMethodError, it loops
        raise "no method found: '#{m}'"
    end
end

end

s2 = String2.new("pipo")

test Delegated method

pp s2.size

call with method_missing()

pp s2.dummy

output (ruby -v ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux])

:!ruby draft/tdelegate.rb
4
draft/tdelegate.rb:24:in rescue in method_missing': no method found: 'bla' (RuntimeError)
from draft/tdelegate.rb:20:in
method_missing'
from draft/tdelegate.rb:16:in dummy'
from draft/tdelegate.rb:32:in
'

Updated by sylvain303 (Sylvain Viart) over 8 years ago

The Issue topic could be rewritten: "DelegateClass don't lookup toplevel method in 1.9.2"

Reading and patching the delegate.rb:http://redmine.ruby-lang.org/projects/ruby-19/repository/entry/lib/delegate.rb I've found that it's related to BasicObject's behavior. DelegateClass somewhat inherit from BasicObject, not Object.

This issue follow the same pattern as #3768.

The documentation should be updated how to fix that (toplevel method resolution).

But may be, I'm still miss something about the new Spec about DelegateClass.

Updated by sylvain303 (Sylvain Viart) over 8 years ago

Fixed DelegateClass with method_missing(), somewhat ugly right?

require 'delegate'

def hello
:hello
end

class MyInt < DelegateClass(Integer)
def initialize(value)
@i = value
super(@i)
# I want some toplevel here
hello (paul aron) = hello()
end

def method_missing(m, *args, &block)
    if __getobj__.respond_to?(m)
        __getobj__.__send__(m, *args, &block)
    else
        Object.send(m, *args, &block)
    end
end

end

ii = MyInt.new(2)
puts p"should call Integer#to_si: #{ii}"
puts "ii.class=#{ii.class}"

output ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]

should call Integer#to_si: 2
ii.class=MyInt

Also available in: Atom PDF