je serais enclin à préfixer à la classe un module anonyme créé dynamiquement dont les méthodes utilisent par exemple super
appeler une méthode d'instance de la classe du même nom, après l'impression d'un message d'entrée de méthode et avant d'imprimer un message de sortie de méthode.
Commençons par créer une classe avec deux méthodes d'instance, on passe un bloc lorsqu'il est impliqué.
class C
def mouse(nbr_mice, impairment)
puts "%d %s mice" % [nbr_mice, impairment]
end
def hubbard(*args)
puts yield args
end
end
C.ancestors
#=> [C, Object, Kernel, BasicObject]
c = C.new
c.mouse(3, 'blind')
# 3 blind mice
c.hubbard('old', 'mother', 'hubbard') { |a| a.map(&:upcase).join(' ') }
# OLD MOTHER HUBBARD
Maintenant, nous construisons une méthode qui crée le module anonyme et l'ajoute à la classe.
def loggem(klass, *methods_to_log)
log_mod = Module.new do
code = methods_to_log.each_with_object('') { |m,str| str <<
"def #{m}(*args); puts \"entering #{m}\"; super; puts \"leaving #{m}\"; end\n" }
class_eval code
end
klass.prepend(log_mod)
end
Nous sommes maintenant prêts à invoquer cette méthode avec les arguments correspondant à la classe à laquelle le module doit être préfixé et les méthodes d'instance de cette classe qui doivent être connectés.
loggem(C, :mouse, :hubbard)
C.ancestors
#=> [#<Module:0x007fedab9ccf48>, C, Object, Kernel, BasicObject]
c = C.new
c.method(:mouse).owner
#=> #<Module:0x007fedab9ccf48>
c.method(:mouse).super_method
#=> #<Method: Object(C)#mouse>
c.method(:hubbard).owner
#=> #<Module:0x007fedab9ccf48>
c.method(:hubbard).super_method
#=> #<Method: Object(C)#hubbard>
c.mouse(3, 'blind')
# entering mouse
# 3 blind mice
# leaving mouse
c.hubbard('old', 'mother', 'hubbard') { |a| a.map(&:upcase).join(' ') }
# entering hubbard
# OLD MOTHER HUBBARD
#leaving hubbard
Voir Module::new et Module#prepend.
exactement ce dont j'avais besoin. THX – amadain