Class: Module

Inherits:
Object show all
Defined in:
lib/wrap_method.rb

Overview

Instance Method Summary collapse

Instance Method Details

#post_condition(*method_names, &block1) ⇒ Object



135
136
137
# File 'lib/wrap_method.rb', line 135

def post_condition(*method_names, &block1)
  pre_and_post_condition(false, true, *method_names, &block1)
end

#pre_and_post_condition(pre, post, *method_names, &block1) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/wrap_method.rb', line 139

def pre_and_post_condition(pre, post, *method_names, &block1)
  method_names.flatten.each do |method_name|
    wrap_method(method_name) do |org_method, args2, block2, obj2|
      block1.call(obj2, method_name, args2, block2)   if pre

      res     = org_method.call(*args2, &block2)      if org_method

      block1.call(obj2, method_name, args2, block2)   if post

      res
    end
  end
end

#pre_condition(*method_names, &block1) ⇒ Object

Since adding code at the beginning or at the end of an instance method is very common, we simplify this by providing the next methods. Althoug they’re named *_condition, they’re not checking anything. They should be named *_action. But pre_action is harder to remember than pre_condition. So I stick to the latter.



131
132
133
# File 'lib/wrap_method.rb', line 131

def pre_condition(*method_names, &block1)
  pre_and_post_condition(true, false, *method_names, &block1)
end

#wrap_method(*method_names, &block1) ⇒ Object

This wrap_method is low-level stuff. If you just want to add code to a method, scroll down to pre_condition and post_condition. They’re much easier to use.

Raises:

  • (ArgumentError)


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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/wrap_method.rb', line 23

def wrap_method(*method_names, &block1)
  raise ArgumentError, "method_name is missing"       if method_names.empty?
  raise ArgumentError, "block is missing"             unless block1

  Thread.exclusive do
    method_names.flatten.each do |method_name|
      count =
      Module.module_eval do
        @_wm_count_ ||= 0
        @_wm_count_ +=1
      end

      module_eval "\n        # Get the method which is to be wrapped.\n        method = instance_method(:\"\#{method_name}\")   rescue nil\n\n        # But it shouldn't be defined in a super class...\n        if method.to_s != \"#<UnboundMethod: \" + self.to_s + \"#\#{method_name}>\"\n          method      = nil\n        end\n\n        if method.nil? and ($VERBOSE or $DEBUG)\n          $stderr.puts \\\n            \"Wrapping a non-existing method [\"+self.to_s+\"#\#{method_name}].\"\n        end\n\n        # Store the method-to-be-wrapped and the wrapping block.\n        define_method(:\"_wm_previous_\#{method_name}_\#{count}_\") do\n          [method, block1]\n        end\n\n        # Avoid this stupid \"warning: method redefined\".\n        unless :\#{method_name} == :initialize\n          undef_method(:\"\#{method_name}\")     rescue nil\n        end\n\n          # Define __class__ and __kind_of__.\n\n        define_method(:__class__) \\\n                  {Object.instance_method(:class).bind(self).call}\n\n        define_method(:__kind_of__) \\\n                  {|s| Object.instance_method(:\"kind_of?\").bind(self).call(s)}\n\n          # Define the new method.\n\n        def \#{method_name}(*args2, &block2)\n          if self.__kind_of__(Module)\n            context   = metaclass\n          else\n            context   = self.__class__\n          end\n\n          # Retrieve the previously stored method-to-be-wrapped (old),\n          # as well as the wrapping block (new).\n          # Note: An UnboundMethod of self.superclass.metaclass can't be\n          # bound to self.metaclass, so we \"walk up\" the class hierarchy.\n          previous    = context.instance_method(\n                            :\"_wm_previous_\#{method_name}_\#{count}_\")\n\n          begin\n            previous  = previous.bind(zelf ||= self)\n          rescue TypeError => e\n            retry     if zelf = zelf.superclass\n          end\n\n          old, new    = previous.call\n\n          # If there's no method-to-be-wrapped in the current class, we \n          # should look for it in the superclass.\n          old ||=\n            context.superclass.instance_method(:\"\#{method_name}\") rescue nil\n\n          # Since old is an unbound method, we should bind it.\n          # Note: An UnboundMethod of self.superclass.metaclass can't be\n          # bound to self.metaclass, so we \"walk up\" the class hierarchy.\n          begin\n            old &&= old.bind(zelf ||= self)\n          rescue TypeError => e\n            retry     if zelf = zelf.superclass\n          end\n\n            # Finally...\n\n          new.call(old, args2, block2, self)\n        end\n      EOF\n    end\n  end\nend\n"

#wrap_module_method(*method_names, &block1) ⇒ Object

Deprecated



115
116
117
118
119
120
121
122
# File 'lib/wrap_method.rb', line 115

def wrap_module_method(*method_names, &block1)        # Deprecated
  if $VERBOSE or $DEBUG
    $stderr.puts "Module#wrap_module_method is deprecated."
    $stderr.puts "Use aModule.metaclass.wrap_method instead."
  end

  metaclass.wrap_method(*method_names, &block1)
end