2009-12-07 6 views
6

Je sais que la méthode class indique quel est le nom de la classe d'un objet, comment pourrais-je connaître le nom de la méthode invoquante? Y a-t-il un moyen de le savoir?Existe-t-il un moyen de connaître la méthode d'invocation?

+4

Non pas que ce n'est pas une question valable et tout, mais avoir à regarder l'appel pile signifie généralement que vous faites quelque chose de mal. –

Répondre

10

Examining the Ruby Call Stack parts cette information:

Avez-vous déjà voulu regarder la pile d'appel sans soulever une exception pour le faire?

caller.each {|c| puts c} 
3

appelant est une méthode Kernal qui vous permet de le faire, alors l'appelant [0] vous permettra de connaître l'appelant immédiat de la fonction.

un hack rapide pour obtenir que le nom de la fonction pourrait être

caller[0][/`\S+/].chop[1..-1] 

ce renverront le nom de la méthode d'appel en tant que chaîne, que vous pouvez ensuite utiliser comme vous le voulez

1

Ruby l'implémentation de Kernel#caller a été faite avec String pour des raisons de performances et de collecte des ordures. Si vous voulez faire une analyse plus sophistiquée de la pile d'appels, jetez un oeil à ce blog:

http://eigenclass.org/hiki/ruby+backtrace+data

L'auteur passe par deux implémentations différentes d'une meilleure pile appel objet graphique, celui mis en oeuvre en Ruby pur avec le (pas très connu) Kernel#set_trace_func méthode et un autre qui fonctionne comme une extension C à l'IRM.

Une application de production ne doit pas utiliser autre chose que l'implémentation Kernel#caller fournie avec Ruby. Si vous utilisez largement les extensions ci-dessus, vous finirez probablement par tuer la capacité de Ruby à collecter efficacement les ordures et ralentir votre processus (j'estime) jusqu'à plusieurs ordres de grandeur.

0

Vous pouvez écrire quelque chose comme ceci:

module Kernel 
    private 
    def who_is_calling? # Or maybe def who_just_called? 
    caller[1] =~ /`([^']*)'/ and $1 
    end 
end 

Et puis vous avez ces petits tests:

irb(main):056:0* def this_is_a_method 
irb(main):057:1>  puts "I, 'this_is_a_method', was called upon by: '#{who_is_calling?}'" 
irb(main):058:1> end 
=> nil 
irb(main):059:0> def this_is_a_method_that_calls_another 
irb(main):060:1>  this_is_a_method 
irb(main):061:1> end 
=> nil 
irb(main):062:0> this_is_a_method_that_calls_another 
I, 'this_is_a_method', was called upon by: 'this_is_a_method_that_calls_another' 
=> nil 
irb(main):063:0> this_is_a_method 
I, 'this_is_a_method', was called upon by: 'irb_binding' 
=> nil 
irb(main):064:0>