Robert Klemme wrote:
> 2006/5/21, uncutstone wu <uncutstone / sina.com>:
>> Then I can get this kind of result:
>>
>> call method hello of class HelloBye
>> hello
>> return from method hello of class HelloBye
> 
> I once hacked something quite complex together that supports multiple
> hooks and threads. The code is on the Wiki
> http://wiki.rubygarden.org/Ruby/page/show/MethodHooks
> 
> Kind regards
> 
> robert

I did something similar:

class Object

  @@methods = {}
  @@pre     = {}
  @@post    = {}

  def self.new_method(m)
    define_method(m) do |*args|
      call_pres m, args
      result = @@methods[m].bind(self).call *args
      call_posts m, args
      result
    end
  end

  def self.wrap( method, wrapping_method )
    @@methods[method] ||= instance_method(method).clone
    define_method(method) do |*args|
      send wrapping_method, @@methods[method].bind(self), *args
    end
  end

  def self.pre( method, pre_method )
    @@methods[method] ||= instance_method(method).clone
    (@@pre[method] ||= []) << pre_method
    new_method method
  end

  def self.post( method, post_method )
    @@methods[method] ||= instance_method(method).clone
    (@@post[method] ||= []) << post_method
    new_method method
  end

  def call_pres( method, arguments )
    return unless @@pre[method]
    @@pre[method].each do |pre|
      send pre, *arguments
    end
  end

  def call_posts( method, arguments )
    return unless @@post[method]
    @@post[method].each do |post|
      send post, *arguments
    end
  end

end

You could hookup before and after methods:

class Test

  def add(one, two)
    result = one + two
    puts "#{one} + #{two} = #{result}"
    result
  end

  pre :add, :pre_add

  def pre_add one, two
    puts "adding #{one} and #{two}"
  end

  post :add, :post_add

  def post_add( one, two )
    puts "done adding #{one} and #{two}"
  end

end

Test.new.add 1, 2
# results in:
# adding 1 and 2
# 1 + 2 = 3
# done adding 1 and 2
# => 3

You can also wrap methods:

class Test

  def subtract( one, two )
    result = one - two
    puts "#{one} - #{two} = #{result}"
    result
  end

  wrap :subtract, :wrap_subtract

  def wrap_subtract( subtracter, one, two )
    puts "about to subtract #{one} and #{two}..."
    subtracter.call one, two
    puts "done..."
  end

end

Test.new.subtract 3, 2
# results in
# about to subtract 3 and 2...
# 3 - 2 = 1
# done...
# => nil

And off course hooking up on hooks places them inside the method chain.

-- 
Posted via http://www.ruby-forum.com/.