domingo, 17 de octubre de 2010

Anidamiento de módulos en ruby

Tal y como ocurre en python con los decoradores, cuando se programa un módulo en ruby debería dejarse la puerta abierta a que no fuera el único.

En el siguiente ejemplo tenemos dos módulos (Printable y Serializable), ambos métodos se deben poder combinar en cualquier orden y pudiendo aparecer uno, ninguno o ambos.

La clave para que un mismo método se ejecute en la clase y en cada uno de sus módulos, es la llamada a super.

En otros lenguajes esto no sería correcto, puesto que los módulos Printable y Serializable no son superclase de la clase Test, pero en ruby, super no llama exactamente a la superclase, sino que repite el mismo método que se está ejecutando obviando la definición actual.

module Printable
def print_method
super
puts "I'm printable"
end
end

module Serializable
def print_method
super
puts "I'm serializable"
end
end


class Test
include Printable
include Serializable

def method_missing(method, *args, &block)
super if method.to_s != 'print_method'
end

def print_method
super
puts "I'm object of Test class"
end

end

t = Test.new
t.print_method

Con este planteamiento hay un problema añadido, al final de la cadena de llamadas a print_method estará la clase de la que hereda Test, y esta clase no tiene porqué tener implementado print_method.

Para solucionarlo en este caso se redefine el method_missing, cuando llegue el momento de ejecutar el método en alguna clase/módulo que no lo entienda, se corta la cadena de ejecuciones.

I'm printable
I'm serializable
I'm object of Test class