Utilizzando chiamate a metodi dinamici (#send
o #method
) la visibilità dei metodi 'viene ignorata.
C'è un modo semplice per chiamare dinamicamente un metodo che fallirà chiamando un metodo privato?come chiamare dinamicamente un metodo rispettando la privacy
risposta
Come so - è necessario metodo 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
Pensavo che non capisco perché si desidera farlo, è possibile utilizzare 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 è davvero male È necessario verificare in anticipo, se m contiene veramente solo un nome di metodo. 'l =" inspect; \ 'rm -rf * \'; puts "" Allora l'attaker proverà a ingannarti pensando a qualcosa che ti assomiglia a un nome di metodo, ma in realtà non lo è. – johannes
Se si utilizza ruby-1.9, è possibile utilizzare Object#public_send
che fa quello che si vuole.
Se si utilizza rubino 1.8.7 o precedente si deve scrivere il proprio 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
Oppure si potrebbe scrivere il proprio Object#public_method
che si comporta come Object#method
ma solo per i metodi pubblici
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
È vero però, eval è davvero l'unico modo per farlo in realtà pre-1.9. Se vuoi saperne di più sulla visibilità, Jamis Buck ha scritto uno awesome article su che cosa significa in realtà la visibilità del metodo in Ruby.
Proprio come le altre cose in Ruby, la visibilità è sempre leggermente diversa dalle altre lingue.
Uso public_send
invece di send
:
my_object.public_send :method, *args
E 'nuovo a Ruby 1.9, quindi per anziani Ruby, è possibile require 'backports/1.9.1/kernel/public_send'
.
Se si vuole evitare eval
, send
o public_send
, o se si vuole better performance, utilizzare i public_method
method:
obj.public_method('my_method_name').call
È possibile aggiungere argomenti come questo:
obj.public_method('my_method_name').call('some_argument_1', 'some_argument_2')
- 1. Chiamare dinamicamente un metodo in Swift
- 2. Come posso chiamare dinamicamente un metodo su un oggetto dinamico?
- 3. Come chiamare dinamicamente un metodo di estensione generico?
- 4. Come chiamare dinamicamente un metodo di classe in .NET?
- 5. Chiamare dinamicamente una dll e un metodo con argomenti
- 6. Come chiamare dinamicamente un modulo in Erlang?
- 7. come chiamare dinamicamente una funzione in C#
- 8. Chiamare dinamicamente metodo sull'interfaccia {} indipendentemente dal tipo di ricevitore
- 9. Come chiamare dinamicamente un metodo da un componente diverso usando cfscript?
- 10. Chiamare un metodo NSTimer
- 11. Come posso chiamare un metodo Client SignalR dinamicamente selezionato da un IHubContext?
- 12. Come aggiungere dinamicamente un metodo di classe?
- 13. Come chiamare un metodo Objective-C da un metodo C?
- 14. Come chiamare un puntatore al metodo da un altro metodo
- 15. Come chiamare un metodo da un altro metodo nell'obiettivo C?
- 16. Come chiamare un metodo non const da un metodo const?
- 17. Come chiamare un metodo tratto con alias
- 18. Come chiamare un metodo di una classe?
- 19. Come proibire di chiamare un metodo C#
- 20. Come chiamare un metodo di servizio Web?
- 21. Assegnare dinamicamente metodo/metodo come variabile
- 22. Come chiamare un metodo statico in C#
- 23. Chiamare un metodo come un metodo di estensione richiede più di riferimento che chiamare direttamente
- 24. Come chiamare un metodo generico tramite riflessione
- 25. Come chiamare un metodo implicitamente dopo ogni chiamata di metodo?
- 26. Rendi la classe iterable rispettando l'ereditarietà
- 27. Richiamare dinamicamente un metodo SOAP per nome?
- 28. Test white-box in Javascript: come gestire la privacy?
- 29. Come chiamare dinamicamente un metodo in Elixir, specificando sia il nome del modulo che quello del metodo?
- 30. jQuery validator - Impossibile chiamare il metodo 'call' di errore non definito - aggiungendo dinamicamente la validazione
questo non è disponibile in ruby 1.8.7 – johannes
In realtà, l'invio è sufficiente in 1.9 credo. Si dice che mandi le cure nel 1.9 ma __send__ no. Ma non l'ho confermato. –