Overriding method calls in Ruby?

metaprogramming, ruby

Solution

Use `alias` or `alias_method`:

# the current implementation of Test, defined by someone else
# and for that reason we might not be able to change it directly
class Test
  def self.items
    @items ||= []
  end
end

# we open the class again, probably in a completely different
# file from the definition above
class Test
  # open up the metaclass, methods defined within this block become
  # class methods, just as if we had defined them with "def self.my_method"
  class << self
    # alias the old method as "old_items"
    alias_method :old_items, :items
    # redeclare the method -- this replaces the old items method,
    # but that's ok since it is still available under it's alias "old_items"
    def items
      # do whatever you want
      puts "items was called!"
      # then call the old implementation (make sure to call it last if you rely
      # on its return value)
      old_items
    end
  end
end

I rewrote your code using the `class << self` syntax to open up the metaclass, because I'm not sure how to use `alias_method` on class methods otherwise.

Problem

I'm trying to get a callback when any method on a particular class is called. Overriding "send" doesn't work. It seems send doesn't get called in normal Ruby method invocation. Take the following example. ``` class Test def self.items @items ||= [] end end ``` If we override send on Test, and then call Test.items, send doesn't get called. Is what I'm trying to do possible? I'd rather not use set_trace_func, since it'll probably slow down things considerably.

Original source