Rolling your own AOP

I’ve been experimenting to see how easy it is to do AOP kinds of things with
Ruby. I know I could use the AspectR package and probably should do that,
but I wanted to see what was involved. Here’s an example of how you could
specify code that you want to run at the beginning of each method in some
class. It just prints “calling foo” where foo is the name of the method
being executed. Feel free to suggest ways I could improve this code.

···

class Demo
def methodA
puts 'methodA is running’
end

def methodB
puts 'methodB is running’
end
end

module AOP
def AOP.addBeforeAdvice(klass, &advice)
# Add the advice code block as a class variable
# of the class being instrumented.
klass.class_eval “@@beforeAdvice = advice”

# For each instance method in the class, excluding inherited methods ...
for method_name in klass.instance_methods(false) do
  new_name = "__#{method_name}"
  klass.class_eval <<-HERE
    # Create an alias for the method.
    alias_method :#{new_name}, :#{method_name}
    
    # Redefine the method.
    def #{method_name}
      # Execute the advice code.
      @@beforeAdvice.call(self)
      # Execute the original method.
      #{new_name}
    end
  HERE
end

end
end

def currentMethodName

Get 2nd to last entry in call stack,

take the last word and remove the quotes around it.

caller[-2].split.last[1…-2]
end

if $0 == FILE
AOP.addBeforeAdvice(Demo) {
puts “calling #{currentMethodName}”
}

o = Demo.new
o.methodA
o.methodB
end


The output is
calling methodA
methodA is running
calling methodB
methodB is running


A.G. Edwards & Sons’ outgoing and incoming e-mails are electronically
archived and subject to review and/or disclosure to someone other
than the recipient.