Forum: Ruby how to wrap method of singleton class

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ittay D. (Guest)
on 2008-11-21 16:44
(Received via mailing list)
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
James C. (Guest)
on 2008-11-21 17:22
(Received via mailing list)
> 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.
Ittay D. (Guest)
on 2008-11-21 21:45
(Received via mailing list)
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>
This topic is locked and can not be replied to.