Proxying method calls

How do I safely proxy method calls from one class to another, as a
fallback for when the main class doesn't respond to the call in
question? Is my implementation of respond_to? and method_missing below
correct (passing tests at bottom)?

class A
    def initialize
        @b = B.new
    end

    def respond_to? call
        unless super call
            @b.respond_to? call
        end
    end

    def method_missing call
        if @b.respond_to? call
            @b.send call
        else
            super
        end
    end
end

class B
    def b
        'b'
    end
end

require 'test/unit'

class MethodTest < Test::Unit::TestCase
    def setup
        @a = A.new
    end

    def test_method_missing
        assert_equal 'b', @a.b
        assert_raise NoMethodError do
            @a.c
        end
    end

    def test_respond_to
        assert @a.respond_to? :b
        assert_equal false, @a.respond_to?(:c)
    end
end

Thomas

How do I safely proxy method calls from one class to another, as a
fallback for when the main class doesn't respond to the call in
question? Is my implementation of respond_to? and method_missing below
correct (passing tests at bottom)?

class A
    def initialize
        @b = B.new
    end

    def respond_to? call
        unless super call
            @b.respond_to? call
        end
    end

I am wary about respond_to? - usually I would not bother to override this. The reason is that there is no guarantee that an object really responds to the method if respond_to? returns "true" - and the other way round.

    def method_missing call
        if @b.respond_to? call
            @b.send call
        else
            super
        end
    end

There is at least one issue: you do not propagate method arguments properly. Better do

     def method_missing(*args, &block)
       @b.send(*args, &block)
     end

Delegating to super is only necessary if the super class also implements method_missing. Otherwise you'll get an exception from @b anyway.

Please see also classes Delegator and SimpleDelegator.
http://ruby-doc.org/stdlib/libdoc/delegate/rdoc/index.html

Kind regards

  robert

···

On 04/20/2010 11:48 PM, Thomas Allen wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/