Defining “method_called”.. How do I make a hook method which gets called every t

原文来自: http://stackoverflow.com/questions/3236194/defining-method-called-how-do-i-make-a-hook-method-which-gets-called-every-t

 

I want to make a hook method which gets called everytime any function of a class gets called. I have tried method_added, but it executes only once at the time of class definition,

 

class Base

  def self.method_added(name)
    p "#{name.to_s.capitalize} Method's been called!!"
  end
  def a
    p "a called."
  end
  def b
    p "b called."
  end
end
t1 = Base.new
t1.a
t1.b
t1.a
t1.b

Output:

"A Method's been called!!"
"B Method's been called!!"
"a called."
"b called."
"a called."
"b called."

 

 but my requirement is that any function of a class that gets called anywhere in the program triggers the "method_called", hook method.

 

Expected Output:
"A Method's been called!!"
"a called."
"B Method's been called!!"
"b called."
"A Method's been called!!"
"a called."
"B Method's been called!!"
"b called."

 If there is any defined existing hook method that works just the same, then please tell about it.

 

Thanks in advance..

Take a look at Kernel#set_trace_func. It lets you specify a proc which is invoked whenever an event (such as a method call) occurs.

class Base
  def a
    puts "in method a"
  end

  def b
    puts "in method b"
  end
end

set_trace_func proc { |event, file, line, id, binding, classname|
  # only interested in events of type 'call' (Ruby method calls)
  # see the docs for set_trace_func for other supported event types
  puts "#{classname} #{id} called" if event == 'call'
}

b = Base.new
b.a
b.b

 

 Outputs:

Base a called
in method a
Base b called
in method b
 

最佳答案:

class Base
  def self.method_added(name)
    if /hook/.match(name.to_s) or method_defined?("#{name}_without_hook")
      return
    end
    hook = "def #{name}_hook\n p 'Method #{name} has been called'\n #{name}_without_hook\nend"
    self.class_eval(hook)

    a1 = "alias #{name}_without_hook #{name}"
    self.class_eval(a1)

    a2 = "alias #{name} #{name}_hook"
    self.class_eval(a2)
  end
  def a
    p "a called."
  end
  def b
    p "b called."
  end
end
t1 = Base.new
t1.a
t1.b
t1.a
t1.b
 

你可能感兴趣的:(method)