How to wrap method of singleton class

Hi,

Given a class:

class Foo

  class << self

    def foo

      puts 'foo'

    end

  end

end

How do I write a module, so that when included in Foo it will wrap the method foo so that Foo.foo will print:

bar

foo

?

Thank you

Ittay

···

--
--
Ittay Dror <ittay.dror@gmail.com>

How do I write a module, so that when included in Foo it will wrap the
method foo so that Foo.foo will print:

You can't (at least not without doing some sneaky metaprogramming -- this
code is still a work in progress: http://gist.github.com/25104\). A class's
own methods take precedence over any modules mixed into it. What you can do
is reopen the singleton class and store a reference to the old method:

class << Foo # Foo singleton class
  old_foo = Foo.method(:foo)
  define_method(:foo) do |*args|
    old_result = old_foo.call(*args)
    old_result.upcase
  end
end

Foo.foo #=> "FOO"

You must use define_method for this instead of def. def does not use a block
so you won't get a closure, which you need to retain visibility of the
old_foo variable.

James Coglan wrote:

How do I write a module, so that when included in Foo it will wrap the
method foo so that Foo.foo will print:
    
You can't (at least not without doing some sneaky metaprogramming -- this
code is still a work in progress: http://gist.github.com/25104\). A class's
own methods take precedence over any modules mixed into it. What you can do
is reopen the singleton class and store a reference to the old method:

class << Foo # Foo singleton class
  old_foo = Foo.method(:foo)
  define_method(:foo) do |*args|
    old_result = old_foo.call(*args)
    old_result.upcase
  end
end

doing it this way, i can do:
class << Foo
  alias_method :original, :foo
  def foo
     puts 'bar'
     original
  end
end

but i want a module i can mix in. (for regular methods, the module can use the included callback to alias the methods, just not sure how to do that for a singleton class)

···

Foo.foo #=> "FOO"

You must use define_method for this instead of def. def does not use a block
so you won't get a closure, which you need to retain visibility of the
old_foo variable.

--
Ittay Dror <ittayd@tikalk.com>
Tikal <http://www.tikalk.com>
Tikal Project <http://tikal.sourceforge.net>

--
--
Ittay Dror <ittay.dror@gmail.com>