Ruby Language
método_missing
Buscar..
Parámetros
Parámetro | Detalles |
---|---|
método | El nombre del método que se ha llamado (en el ejemplo anterior es :say_moo , tenga en cuenta que este es un símbolo. |
* args | Los argumentos pasaron a este método. Puede ser cualquier número, o ninguno |
&bloquear | El bloque del método llamado, puede ser un bloque do o un bloque encerrado { } |
Observaciones
Siempre llama super, en la parte inferior de esta función. Esto guarda un fallo silencioso cuando se llama a algo y no recibe un error.
Por ejemplo, este method_missing va a causar problemas:
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say"
speak
end
end
end
=> Animal.new.foobar
=> nil # This should really be raising an error
method_missing
es una buena herramienta para usar cuando sea apropiado, pero tiene dos costos que debe considerar. Primero, method_missing
es menos eficiente: Ruby debe buscar en la clase y en todos sus ancestros antes de poder recurrir a este enfoque. esta penalización de rendimiento puede ser trivial en un caso simple, pero puede sumar. En segundo lugar, y más ampliamente, esta es una forma de meta-programación que tiene un gran poder que viene con la responsabilidad de garantizar que la implementación sea segura, que maneje adecuadamente las entradas maliciosas, las entradas inesperadas, etc.
También deberías anular la respond_to_missing?
al igual que:
class Animal
def respond_to_missing?(method, include_private = false)
method.to_s.start_with?("say_") || super
end
end
=> Animal.new.respond_to?(:say_moo) # => true
Atrapar llamadas a un método indefinido
class Animal
def method_missing(method, *args, &block)
"Cannot call #{method} on Animal"
end
end
=> Animal.new.say_moo
> "Cannot call say_moo on Animal"
Usando el método que falta
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say"
speak
else
super
end
end
end
=> a = Animal.new
=> a.say_moo
=> "moo"
=> a.shout_moo
=> NoMethodError: undefined method `shout_moo'
Usar con bloque
class Animal
def method_missing(method, *args, &block)
if method.to_s == 'say'
block.call
else
super
end
end
end
=> Animal.new.say{ 'moo' }
=> "moo"
Utilizar con parametro
class Animal
def method_missing(method, *args, &block)
say, speak = method.to_s.split("_")
if say == "say" && speak
return speak.upcase if args.first == "shout"
speak
else
super
end
end
end
=> Animal.new.say_moo
=> "moo"
=> Animal.new.say_moo("shout")
=> "MOO"