Instance_eval with method proc

Hi

I'm trying to invoke a method defined in one class with self set to an
instance of a different class. I didn't have much success (as shown
below). Is there another way to achieve this?

Many thanks

Paul

···

----

class Foo
  def foo
    print
  end

  def print
    puts "foo"
  end

  def test bar
    foo_proc = Proc.new { print }

    # Prints bar
    bar.instance_eval(&foo_proc)

    # 1.8.6 Fails with "wrong number of arguments (1 for 0) (ArgumentError)"
    # 1.9.1 Prints foo
    bar.instance_eval(&method(:foo))
  end
end

class Bar
  def print
    puts "bar"
  end
end

Foo.new.test Bar.new

Paul Carey wrote:

I'm trying to invoke a method defined in one class with self set to an
instance of a different class.

If the method is in a common superclass, then you can make an
UnboundMethod and bind it to the new object. e.g.

class Foo; def foo; puts inspect; end; end

=> nil

class Bar < Foo; end

=> nil

b = Bar.new

=> #<Bar:0xb7c04998>

Foo.instance_method(:foo).bind(b).call

#<Bar:0xb7c04998>
=> nil

But otherwise I don't think you can detach arbitrary methods from one
class and apply them to an object of an unrelated class. You'd probably
be best putting the relevant method(s) in a mixin, and then sharing that
between the classes, or adding those methods to the singleton class of
the individual object you're interested in.

module Baz; def baz; puts "baz!"; end; end

=> nil

s = "hello"

=> "hello"

s.extend Baz

=> "hello"

s.baz

baz!
=> nil

···

--
Posted via http://www.ruby-forum.com/\.

Brian Candler wrote:

If the method is in a common superclass, then you can make an
UnboundMethod and bind it to the new object. e.g.

class Foo; def foo; puts inspect; end; end

=> nil

class Bar < Foo; end

=> nil

b = Bar.new

=> #<Bar:0xb7c04998>

Foo.instance_method(:foo).bind(b).call

#<Bar:0xb7c04998>
=> nil

... and of course, object b usually has the 'foo' method already
inherited from the parent, in which case b.send(:foo) is sufficient.

But if 'foo' has been overridden, it can still be useful to bind this
way.

class Foo; def foo; puts "foo from parent"; end; end

=> nil

class Bar < Foo; def foo; puts "foo from child"; end; end

=> nil

b = Bar.new

=> #<Bar:0xb7cf1cfc>

b.send(:foo)

foo from child
=> nil

m = Foo.instance_method(:foo)

=> #<UnboundMethod: Foo#foo>

m.bind(b).call

foo from parent
=> nil

···

--
Posted via http://www.ruby-forum.com/\.

I'm trying to invoke a method defined in one class with self set to an
instance of a different class.

You'd probably be best ... or adding those methods to the singleton
class of the individual object you're interested in.

Thanks Brian, I went with adding the methods to the singleton class.
Paul