Usando llamadas a métodos dinámicos (#send
o #method
) se ignora la visibilidad de los métodos.
¿Hay una manera simple de llamar dinámicamente a un método que fallará llamando a un método privado?cómo llamar dinámicamente a un método respetando la privacidad
Respuesta
Como sé, necesita el método public_send:
----------------------------------------------------- Object#public_send obj.public_send(symbol [, args...]) => obj From Ruby 1.9.1 ------------------------------------------------------------------------ Invokes the method identified by _symbol_, passing it any arguments specified. Unlike send, public_send calls public methods only. 1.public_send(:puts, "hello") # causes NoMethodError
Pensé que no entendía por qué quieres hacerlo, puedes usar eval
.
class Klass
private
def private_method(arg)
end
end
k = Klass.new
m = "private_method"
eval "k.#{m}('an arg')"
NoMethodError: private method `private_method' called for #<Klass:0x128a7c0>
from (irb):15
from (irb):15
Eval es realmente malo. Debe verificar de antemano, si m realmente contiene solo un nombre de método. 'l =" inspeccionar; \ 'rm -rf * \ '; puts" 'Entonces el atacante intentará engañarte pensando en algo que te parezca un nombre de método, pero realmente no lo es. – johannes
Si está utilizando rubí-1.9, puede utilizar Object#public_send
el que hace lo que quiere.
Si utilizar rubí 1.8.7 o anterior hay que escribir su propia Object#public_send
class Object
def public_send(name, *args)
unless public_methods.include?(name.to_s)
raise NoMethodError.new("undefined method `#{name}' for \"#{self.inspect}\":#{self.class}")
end
send(name, *args)
end
end
O usted podría escribir su propia Object#public_method
que se comporta como Object#method
pero sólo para los métodos públicos
class Object
def public_method(name)
unless public_methods.include?(name.to_s)
raise NameError.new("undefined method `#{name}' for class `#{self.class}'")
end
method(name)
end
end
Es cierto, eval realmente es, creo que es la única manera de hacerlo realmente antes de 1.9. Si desea leer más sobre la visibilidad, Jamis Buck escribió un awesome article sobre qué método realmente significa la visibilidad en Ruby.
Al igual que otras cosas en Ruby, la visibilidad es ligeramente diferente de otros idiomas.
Uso public_send
en lugar de send
:
my_object.public_send :method, *args
Es nuevo a Ruby 1.9, por lo que para los mayores de Ruby, puede require 'backports/1.9.1/kernel/public_send'
.
Si se quiere evitar eval
, send
o public_send
, o si desea better performance, utilizar los public_method
method:
obj.public_method('my_method_name').call
Puede añadir argumentos de esta manera:
obj.public_method('my_method_name').call('some_argument_1', 'some_argument_2')
- 1. Llamar a un método NSTimer
- 2. Llamar dinámicamente a un dll y a un método con argumentos
- 3. Cómo prohibir llamar a un método C#
- 4. ¿Cómo llamar a un método en Java?
- 5. Llamar a un método anulado, superclase a llamadas reemplazadas método
- 6. ¿Puede un método nativo llamar a un método privado?
- 7. Llamar a un método genérico con un método genérico
- 8. Cómo llamar dinámicamente a los métodos de acceso en Ruby
- 9. Llamar a un método estático en C#
- 10. Llamar a un método asíncrono de un método no asíncrono
- 11. cómo llamar dinámicamente una función en C#
- 12. Cómo llamar a un método en un objeto de javascript
- 13. ¿Cómo puedo llamar a un método en un objeto nulo?
- 14. ¿Cómo agregar dinámicamente un método de clase?
- 15. Llamar a un método en Constructor
- 16. ¿Cómo llamo a un método dinámicamente nombrado en Javascript?
- 17. Llamar a un método miembro no estático desde otro método
- 18. Llamar a un método ApplicationController desde la consola en Rails
- 19. Llamar a un método súper en PHP
- 20. Llamar a un método de otro controlador
- 21. Llamar a un método cada vez antes de llamar a cualquier otro método
- 22. Llamar a un método como un método de extensión requiere más referencia que llamar directamente
- 23. ¿Cómo defino dinámicamente un método como privado?
- 24. Cómo llamar a un método de controlador desde Javascript
- 25. ¿Cómo llamar a un método de C# solo si existe?
- 26. ¿Cómo llamar a un método de servicio web?
- 27. ¿Cómo llamar a un método de una clase?
- 28. ¿Cómo llamar a un método COM complejo de PowerShell?
- 29. Llamar a un método de subclase de la superclase
- 30. Android/Java: ¿Llamar a un método usando la reflexión?
esto no está disponible en ruby 1.8.7 – johannes
En realidad, enviar es suficiente en 1.9 creo. Se rumorea que envía preocupaciones en 1.9 pero __send__ no. Pero no he confirmado esto. –