How to wrap method of singleton class


#1

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


#2

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.


#3

James C. wrote:

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 D. removed_email_address@domain.invalid
Tikal http://www.tikalk.com
Tikal Project http://tikal.sourceforge.net