Il mio approccio a questo sarebbe di avvolgere l'oggetto che sto cercando di accedere con un guscio Logger oggetto che richiama semplicemente l'oggetto originale. Il codice seguente funziona avvolgendo l'oggetto che si desidera registrare con una classe che chiama semplicemente qualsiasi metodo desiderato sull'oggetto sottostante, ma fornisce un modo per intercettare quelle chiamate e registrare (o qualsiasi altra cosa) ogni evento di accesso.
class Test
def self.items
puts " Class Items run"
"Return"
end
def item
puts " Instance item run"
return 47, 11
end
end
class GenericLogger
@@klass = Object # put the class you want to log into @@klass in a sub-class
def initialize(*args)
@instance = @@klass.new(*args)
end
def self.method_missing(meth, *args, &block)
retval = handle_missing(@@klass, meth, *args, &block)
if !retval[0]
super
end
retval[1]
end
def method_missing(meth, *args, &block)
retval = self.class.handle_missing(@instance, meth, *args, &block)
if !retval[0]
super
end
retval[1]
end
def self.handle_missing(obj, meth, *args, &block)
retval = nil
if obj.respond_to?(meth.to_s)
# PUT YOUR LOGGING CODE HERE
if obj.class.name == "Class"
puts "Logger code run for #{obj.name}.#{meth.to_s}"
else
puts "Logger code run for instance of #{obj.class.name}.#{meth.to_s}"
end
retval = obj.send(meth, *args)
return true, retval
else
return false, retval
end
end
end
# When you want to log a class, create one of these sub-classes
# and place the correct class you are logging in @@klass
class TestLogger < GenericLogger
@@klass = Test
end
retval = TestLogger.items
puts "Correctly handles return values: #{retval}"
tl = TestLogger.new
retval = tl.item
puts "Correctly handles return values: #{retval}"
begin
tl.itemfoo
rescue NoMethodError => e
puts "Correctly fails with unknown methods for instance of Test:"
puts e.message
end
begin
TestLogger.itemsfoo
rescue NoMethodError => e
puts "Correctly fails with unknown methods for class Test"
puts e.message
end
uscita da quel codice di esempio è:
Logger code run for Test.items
Class Items run
Correctly handles return values: Return
Logger code run for instance of Test.item
Instance item run
Correctly handles return values: [47, 11]
Correctly fails with unknown methods for instance of Test:
undefined method `itemfoo' for #<TestLogger:0x2962038 @instance=#<Test:0x2962008>>
Correctly fails with unknown methods for class Test
undefined method `itemsfoo' for TestLogger:Class
fonte
2013-09-25 23:48:35
Potrebbe essere possibile farlo aliasando la classe alla mia classe e delegando le chiamate di metodo alla classe originale. –
Protip: tutte le risposte che ti dicono come sovrascrivere un singolo metodo ti dicono anche come farlo con tutti i metodi implementati da una classe. Hai solo bisogno di scorrere su di loro. E 'questa la tua vera domanda? – Chuck