Bug #4994

DelegateClass don't find extern global public method in 1.9.2

Added by sylvain303 (Sylvain Viart) 11 months ago. Updated 10 months ago.

[ruby-core:37864]
Status:Rejected Start date:07/08/2011
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:lib
Target version:1.9.2
ruby -v:ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]

Description

How to reproduce: <pre> 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 </pre> 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: <pre> !ruby draft/tdelegate.rb draft/tdelegate.rb:15:in `dummy': undefined method `test_that?' for "pipo":String2 (NoMethodError) from draft/tdelegate.rb:21:in `<main>' shell returned 1 </pre>

History

Updated by nobu (Nobuyoshi Nakada) 11 months 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) 10 months 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 <pre> 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 </pre> output (ruby -v ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]) <pre> :!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 `<main>' </pre>

Updated by sylvain303 (Sylvain Viart) 10 months 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) 10 months ago

Fixed DelegateClass with method_missing(), somewhat ugly right? <pre> require 'delegate' def hello :hello end class MyInt < DelegateClass(Integer) def initialize(value) @i = value super(@i) # I want some toplevel here @hello = 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}" </pre> output ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux] <pre> should call Integer#to_si: 2 ii.class=MyInt </pre>

Also available in: Atom PDF