Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: Catching All Methods Sent to an Object

I'm making a weird class where I want to catch every method sent to an object of the class. I can achieve most of what I want with method_missing e.g.

class MyClass
    def method_missing m, *args
        # do stuff
    end
end

The problem then is all of the instance methods that MyClass inherits from Object. I could go through each method one-by-one and redefine them, but I was hoping for a more flexible approach. All of the metaprogramming methods I've tried have complained with a NameError when I try to touch those instance methods.

like image 295
Max Avatar asked Aug 25 '11 02:08

Max


3 Answers

As noted in the comments and the answer from @DanCheail, if you're using ruby 1.9+ you should use a BasicObject rather than undefining methods of Object. At the time of this posting usage of 1.8.x was still quite prevalent, even though 1.9 had been released for some time.


Rather than attempting to "redefine" anything, you could wrap your object in a blanked (for the most part) proxy object, something like:

class MyProxy
  instance_methods.each do |meth|
    # skipping undef of methods that "may cause serious problems"
    undef_method(meth) if meth !~ /^(__|object_id)/
  end

  def initialize(object)
    @object = object
  end     

  def method_missing(*args)
    # do stuff
    p args
    # ...
    @object.send(*args)
  end
end

MyProxy.new(MyClass.new).whatever
like image 178
numbers1311407 Avatar answered Oct 12 '22 06:10

numbers1311407


If you're using Ruby 1.9, you can have your class inherit from BasicObject to get a clean slate to work from:

http://ruby-doc.org/core-1.9/classes/BasicObject.html

like image 25
dnch Avatar answered Oct 12 '22 07:10

dnch


If you're using Ruby 1.8 you can consider using the blankslate gem.

like image 1
Moiz Raja Avatar answered Oct 12 '22 05:10

Moiz Raja