Skip to content

Instantly share code, notes, and snippets.

@halilim
Created March 21, 2016 09:02
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save halilim/0ebe4aeb1d9e5d5a58ec to your computer and use it in GitHub Desktop.
A refactoring of TraceCalls (Metaprogramming - Programming Ruby 1.9 & 2.0, 4th edition)
module TraceCalls
def self.included(base)
[base, base.singleton_class].each do |klass|
klass.instance_methods(false).each do |existing_method|
wrap(klass, existing_method)
end
end
def base.method_added(method)
TraceCalls.run_method_added(self, method, __method__)
end
def base.singleton_method_added(method)
TraceCalls.run_method_added(self.singleton_class, method, __method__)
end
end
def self.run_method_added(klass, method, method_added)
klass.instance_eval do
return if method == method_added || @trace_calls_internal
@trace_calls_internal = true
TraceCalls.wrap(klass, method)
@trace_calls_internal = false
end
end
def self.wrap(klass, method)
klass.instance_eval do
method_object = klass.instance_method(method)
define_method(method) do |*args, &block|
puts "==> calling #{method} with #{args.inspect} on #{self}"
result = method_object.bind(self).call(*args, &block)
puts "<== #{method} returned #{result.inspect}"
result
end
end
end
end
class Example
def one(arg)
puts "One called with #{arg}"
end
def self.hi
puts 'hi'
end
end
ex1 = Example.new
ex1.one("Hello")
Example.hi
class Example
include TraceCalls
def two(arg1, arg2)
arg1 + arg2
end
def self.three(arg)
puts "Three called with #{arg}"
3
end
end
ex1.one("Goodbye")
Example.hi
puts ex1.two(4, 5)
puts Example.three("something")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment