Les traigo un truco que los asombrara... con una tenica de hooking aplicada al ruby para poder enganchar los metodos que quieran de cualquier objeto y controlar su ejecucion, asi como registrar llamados a ese metodo , filtrar cosas, etc.
Aca el module q lo hace posible:
hooking.rb
module Hook
def hook( method_name, hook_name = nil, old_method_name = nil)
obj = self
# si no se le pasa el nombre de la funcion que controla el hook
# arma un nombre de funcion
hook_name ||= "#{method_name}_hook"
#lo mismo con el nombre de la variable de instancia
# que almacena la referencia al metodo original
old_method_name ||= "__old__#{method_name}"
# almacenar el metodo original
eval("@#{old_method_name} = self.method( method_name.to_sym)")
# redefinir el metodo para que invoque el metodo de hook, pasandole
# un bloque de codigo que ejecute el metodo original, entonces el metodo
# de hook puede invocar al metodo original usando yield
eval("
def obj.#{method_name}(*x)
self.#{hook_name}(@#{old_method_name},*x) do |*x|
yield(*x) if block_given?
end
end
")
end
end
class Object
# includir el modulo de Hook en Object para que se pueda aplicar a todo Object
include Hook
end
Y ahora un pequeño ejemplo de como podria usarse
main.rb
require "hooking"
class X
def foo( num )
print "metodo foo invocado con num = #{num}\n"
end
def bar
print "metodo bar invocado\n"
[1,2,3].each do |x| yield(x) end
end
end
x = X.new
x.hook(:foo)
def x.foo_hook( foo_original, num )
print "foo invocado\n"
# se invoca al metodo original, pero alterando los parametros
foo_original.call( num+1)
print "fin de foo\n"
end
x.hook :bar
def x.bar_hook( bar_original )
print "bar invocado\n"
bar_original.call do |x|
# tambien se puede alterar y controlar
# el uso de yield del metodo
yield(x+2)
end
print "fin de bar\n"
end
x.foo(3)
x.bar do |x|
print x,"\n"
end
No hay comentarios:
Publicar un comentario