2011-02-24 26 views
116

¿Hay alguna forma en Ruby para encontrar el nombre del método de llamada dentro de un método?¿Cómo obtener el nombre del método de llamada?

Por ejemplo:

class Test 
    def self.foo 
    Fooz.bar 
    end 
end 

class Fooz 
    def self.bar 
    # get Test.foo or foo 
    end 
end 
+1

posible duplicado de [Obtener el nombre del método que se está ejecutando en Ruby] (http://stackoverflow.com/questions/199527/get-the-name-of-the-currently-executing-method-in-ruby) –

+0

obtener objeto de llamada: http://stackoverflow.com/questions/2703136/any-way-to-determination-which-object-called-a-method –

Respuesta

163
puts caller[0] 

o tal vez ...

puts caller[0][/`.*'/][1..-2] 
+2

Eso realmente funciona? –

+4

Sí, vea Kernel # caller, también conocido como http://www.ruby-doc.org/core-1.8.7/classes/Kernel.html#M001073 – DigitalRoss

+0

¡Muchas gracias!:) – jrichardlai

20

utilizo

caller[0][/`([^']*)'/, 1] 
+3

¿Cuál es la ventaja de esto sobre el enfoque de DigitalRoss? –

+2

Más limpio y más preciso. En lugar de hacer la búsqueda, utilice un método de matriz para dividir los caracteres no deseados según la posición (lo que podría ser incorrecto). –

+2

¿Por qué no usar simplemente la persona que llama [0] [/ '(. *) '/, 1]? No soy un gurú sobre expresiones regulares, pero parece funcionar. – collimarco

129

en Ruby 2.0.0, puede utilizar:

caller_locations(1,1)[0].label 

Es much faster que la solución Rubí 1.8+:

caller[0][/`([^']*)'/, 1] 

obtendrá incluido en backports cuando llegue el momento (o una solicitud de extracción!).

+0

Gracias amigo, justo lo que necesitaba. – mhenrixon

+0

Vale la pena señalar que esto no está disponible en Rubinius. – Max

+0

si usas pry, tienes que ignorar la pila stack-pace, parece ... no parece haber una solución predeterminada para eso. – dtc

20

Uso caller_locations(1,1)[0].label (por ruby> = 2,0)

Editar: Mi respuesta estaba diciendo a utilizar __method__ pero estaba equivocado, devuelve el nombre del método actual, ver this gist.

+0

la mejor respuesta! –

+1

@OswaldoFerreira Gracias, lo encontré en SO en otra respuesta en algún lugar – Dorian

+3

Esto es incorrecto, devuelve el método actual, no el método que llamó al método actual ... – thrice801

4

¿Qué tal

caller[0].split("`").pop.gsub("'", "") 

Mucho más limpio de la OMI.

+0

Works https://gist.github.com/Dorian/f8a276bebfc35ff01838 – Dorian

1

En su lugar, puede escribirlo como función de biblioteca y realizar una llamada donde sea necesario. El código es el siguiente:

module CallChain 
    def self.caller_method(depth=1) 
    parse_caller(caller(depth+1).first).last 
    end 

    private 

    # Copied from ActionMailer 
    def self.parse_caller(at) 
    if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at 
     file = Regexp.last_match[1] 
     line = Regexp.last_match[2].to_i 
     method = Regexp.last_match[3] 
     [file, line, method] 
    end 
    end 
end 

para activar el método del módulo anterior es necesario llamar así: caller = CallChain.caller_method

code reference from

+1

Un enlace a una posible solución siempre es bienvenido, pero por favor [agregue contexto alrededor del enlace] (http://meta.stackoverflow.com/a/8259/ 169503) para que los demás usuarios tengan una idea de qué es y por qué está allí. Siempre cite la parte más relevante de un enlace importante, en caso de que el sitio objetivo no esté disponible o esté permanentemente fuera de línea. Tenga en cuenta que ser apenas más que un enlace a un sitio externo es una posible razón para [¿Por qué y cómo se eliminan algunas respuestas?] (Http://stackoverflow.com/help/deleted-answers). –

+0

@ XaviLópez ha actualizado la respuesta, por favor, rectifique si estoy haciendo algo mal o algo equivocado ... gracias por la amable sugerencia :) –

+1

Gracias por mejorar su respuesta. Lamentablemente, no tengo suficiente conocimiento sobre Ruby para poder comentar correctamente sobre esta publicación, pero la respuesta parece correcta ahora. He eliminado mi voto negativo. La mejor de las suertes :-) –

2

Con el fin de ver la persona que llama y la información de destinatario de la llamada en cualquier idioma, ya sea ruby, java o python, siempre querrás mirar el rastro de la pila. En algunos lenguajes, como Rust y C++, hay opciones integradas en el compilador para activar algún tipo de mecanismo de creación de perfiles que pueda ver durante el tiempo de ejecución. Creo que uno existe para Ruby llamado ruby-prof.

Y como se mencionó anteriormente, podría mirar en la pila de ejecución para ruby. Esta pila de ejecución es una matriz que contiene objetos de ubicación de rastreo.

En esencia todo lo que necesita saber acerca de este comando es la siguiente:

persona que llama (start = 1, longitud = nil) → matriz o nula

Cuestiones relacionadas