¿Cómo obtener el nombre del método de llamada?


161

¿Hay alguna manera en Ruby para encontrar el nombre del método de llamada dentro de un método?

Por ejemplo:

class Test
  def self.foo
    Fooz.bar
  end
end

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



No es un duplicado de "Obtener el nombre del método ejecutado actualmente en Ruby". Esta pregunta solicita el nombre del método de llamada, no el nombre del método actual.
Wayne Conrad

Respuestas:


210
puts caller[0]

o quizás...

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

55
Sí, vea Kernel # caller, también conocido
DigitalRoss

10
Eso le da el nombre del método de llamada, pero no da ninguna indicación a qué módulo o clase pertenece el método. ¿Es eso posible?
Thom

@thomthom Sí, eso es posible, puedes llamar a self.class.name para ver el nombre de la clase
Thorin el

Excelente uso de expresiones regulares como un índice de cadena! También se puede usarcaller[0][/`(.*)'/,1]
aks el

1
Esto no parece funcionar en Rails 5.2.1. En el controlador Rails, esto vuelve "block in make_lambda". Supongo que esto es solo para Ruby.
dcangulo

164

En Ruby 2.0.0, puedes usar:

caller_locations(1,1)[0].label

Es mucho más rápido que la solución Ruby 1.8+:

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

Se incluirá backportscuando tenga el tiempo (o una solicitud de extracción).


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

1
si estás usando palanca, tienes que ignorar el rastro de pila de palanca que parece ... no parece haber una solución predeterminada para eso.
dtc

66
Ahora parece estar caller_locations[0].labelen Ruby 2.2.0, de lo contrario, siempre tendrá send_actionresultados
brcebn

1
¿Cómo podemos obtener solo el método de aplicación de llamada e ignorar la llamada de frameworks?
Matrix

31

Uso caller_locations(1,1)[0].label(para ruby> = 2.0)

Editar : mi respuesta decía usar __method__pero estaba equivocado, devuelve el nombre del método actual.


1
@OswaldoFerreira Gracias, lo encontré en SO en otra respuesta en alguna parte
Dorian

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

1
Funciona de maravilla. También parece ser mucho más rápido que los métodos pre 2.0.
Dr.Strangelove

21

yo suelo

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

44
¿Cuál es la ventaja de esto sobre el enfoque de DigitalRoss?
Andrew Grimm

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 en función de la posición (lo que podría ser incorrecto).
Nueva Alejandría

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

77
@collimarco Mientras la Cadena no contenga 'más allá de la que está buscando (y supongo que no puede), el resultado será el mismo, claro. Sin embargo, [^']*funcionará mejor ya que el motor de expresiones regulares dejará de intentar igualar esa parte con la expresión en el momento en que llegue a '(su versión irá al final, luego retrocederá porque no encontró un 'al final). La diferencia es bastante insignificante en este caso, por supuesto, pero es un buen hábito evitar .en expresiones regulares siempre que sea posible.
Thor84no

4

Qué tal si

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

Mucho más limpio imo.


3

En su lugar, puede escribirlo como función de biblioteca y hacer 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, debe llamar así: caller = CallChain.caller_method

código de referencia de


1
Siempre es bienvenido un enlace a una solución potencial, pero agregue contexto alrededor del enlace para que sus 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 no se pueda acceder al sitio de destino o se desconecte permanentemente. Tenga en cuenta que ser apenas más que un enlace a un sitio externo es una posible razón de por qué y cómo se eliminan algunas respuestas. .
Xavi López

@ XaviLópez han actualizado la respuesta, PLZ rectificar si estoy haciendo mal o Somthing equivocada ... thnx para la sugerencia buena :)
Amit karsale

1
Gracias por mejorar tu respuesta. Desafortunadamente, no tengo suficiente conocimiento sobre Ruby para poder comentar adecuadamente sobre esta publicación, pero la respuesta parece correcta ahora. He eliminado mi voto negativo. Mejor suerte :-)
Xavi López

2

Para ver la información de la persona que llama y de la persona que llama en cualquier idioma, ya sea ruby, java o python, siempre querrá ver el seguimiento 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 puede ver durante el tiempo de ejecución. Creo que existe uno para Ruby llamado ruby-prof.

Y como se mencionó anteriormente, puede buscar rubí en la pila de ejecución. Esta pila de ejecución es una matriz que contiene objetos de ubicación de rastreo.

Esencialmente, todo lo que necesita saber sobre este comando es el siguiente:

llamador (inicio = 1, longitud = nulo) → matriz o nulo

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.