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
|
module Logging
# Defines a Proxy that will log all method calls on the proxied object. This
# class uses +method_missing+ on a "blank slate" object to intercept all
# method calls. The method name being called and the arguments are all
# logged to the proxied object's logger instance. The log level and other
# settings for the proxied object are honored by the Proxy instance.
#
# If you want, you can also supply your own +method_missing+ code as a block
# to the constructor.
#
# Proxy.new(object) do |name, *args, &block|
# # code to be executed before the proxied method
# result = @object.send(name, *args, &block)
# # code to be executed after the proxied method
# result # <-- always return the result
# end
#
# The proxied object is available as the "@object" variable. The logger is
# available as the "@logger" variable.
#
class Proxy
# :stopdoc:
KEEPERS = %r/^__|^object_id$|^initialize$/
instance_methods(true).each { |m| undef_method m unless m[KEEPERS] }
private_instance_methods(true).each { |m| undef_method m unless m[KEEPERS] }
# :startdoc:
# Create a new proxy for the given _object_. If an optional _block_ is
# given it will be called before the proxied method. This _block_ will
# replace the +method_missing+ implementation
#
def initialize( object, &block )
Kernel.raise ArgumentError, "Cannot proxy nil" if nil.equal? object
@object = object
@leader = @object.is_a?(Class) ? "#{@object.name}." : "#{@object.class.name}#"
@logger = Logging.logger[object]
if block
eigenclass = class << self; self; end
eigenclass.__send__(:define_method, :method_missing, &block)
end
end
# All hail the magic of method missing. Here is where we are going to log
# the method call and then forward to the proxied object. The return value
# from the proxied objet method call is passed back.
#
def method_missing( name, *args, &block )
@logger << "#@leader#{name}(#{args.inspect[1..-2]})\n"
@object.send(name, *args, &block)
end
end # Proxy
end # Logging
|