From: Robert Feldt Date: 2001-11-03T01:49:05+09:00 Subject: [ruby-talk:24177] A short, pure-Ruby AOP implementation Hi, Couldn't help posting this; its getting late in Sweden and its time to go home... ;-) Have a nice weekend! /R # Friday-late AOP puzzle: Is this the shortest possible pure-Ruby, # call-level AOP implementation? # I'm sure there are many problems with it but its < 30 LOC! class Aerial def initialize(object) @object = object end # Undefine methods so that we can relay them to the real object # Is it really dangerous to undef __id__ and __send__? What can happen? Object.new.methods.each {|m| undef_method(m.intern) unless m =~ /__/} def __pre_all__; end def __post_all__; end def __around_all__; yield; end def method_missing(methodId, *args, &b) @__result__ = @__exit_status__ = nil __around_all__ { __pre_all__(methodId, *args) begin @__result__ = @object.send(methodId, *args, &b) rescue Exception => @__exit_status__ end __post_all__(methodId, *args, &b) } raise @__exit_status__ if @__exit_status__ @__result__ end end if __FILE__ == $0 class Tracer < Aerial def __pre_all__(methodId, *args, &b) print "#{@object.send(:type).inspect}##{methodId.id2name}(#{args.map{|e| e.inspect}.join(', ')})" end def __post_all__(methodId, *args, &b) if @__exit_status__ puts " raised an exception #{@__exit_status__.inspect}" else puts " = #{@__result__.inspect}" end end end t, sum = Tracer.new(Array.new), 0 t.push 1 t.length t.each {|e| sum += e} p sum # And it works with blocks! begin t.dummy rescue end t.pop end