kch (owner)

Revisions

gist: 101456 Download_button fork
public
Description:
dynamically define a method that takes a block in ruby 1.8; inspired by the pragprog metaprogramming screencasts
Public Clone URL: git://gist.github.com/101456.git
Embed All Files: show embed
tracy.rb #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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)