Skip to content

Instantly share code, notes, and snippets.

@kch
Created April 25, 2009 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kch/101456 to your computer and use it in GitHub Desktop.
Save kch/101456 to your computer and use it in GitHub Desktop.
dynamically define a method that takes a block in ruby 1.8; inspired by the pragprog metaprogramming screencasts
module Tracy
def self.included k
k.extend ClassMethods
end
module ClassMethods
def method_added m
wrap_method(m)
end
def previous_method_name(m)
:"previous #{m}"
end
def suppressing_wrap_method
@_wrap_method_suppressed = true
yield
ensure
@_wrap_method_suppressed = false
end
def wrap_method m
return if @_wrap_method_suppressed
suppressing_wrap_method do
alias_method previous_method_name(m), m
alias_method m, :_call_original_method_with_tracing
end
end
def alias_method m0, m1
return super unless method_defined? previous_method_name(m1)
suppressing_wrap_method do
super
super previous_method_name(m0), previous_method_name(m1)
end
end
def define_method m, &b
super
wrap_method(m)
end
end
def _call_original_method_with_tracing *a, &b
m = caller(0).first =~ /`(.+)'$/ && $1
puts ">>>> calling #{m}"
m0 = self.class.previous_method_name(m)
rv = send m0, *a, &b
puts "<<<< returning #{rv.inspect}"
rv
end
end
class Foo
include Tracy
def bar v
yield * v
end
def << x
bar(6){x}
end
alias_method :baz, :<<
end
r = Foo.new
puts r.bar(5){6}
puts r << 4
puts r.baz(4)
m = "nomnom `' `nomnom"
(class << r; self end).send(:define_method, m) { "LOLZ" }
puts r.send(m)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment