Como obter o nome do método de chamada?


161

existe uma maneira no Ruby encontrar o nome do método de chamada dentro de um método?

Por exemplo:

class Test
  def self.foo
    Fooz.bar
  end
end

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



Não é uma duplicata de "Obter o nome do método atualmente executado no Ruby". Esta pergunta pede o nome do método de chamada, não o nome do método atual.
Wayne Conrad

Respostas:


210
puts caller[0]

ou talvez...

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

5
Sim, consulte Kernel # caller, também conhecido como ruby-doc.org/core-1.8.7/classes/Kernel.html#M001073
DigitalRoss

10
Isso fornece o nome do método de chamada, mas não fornece nenhuma indicação a qual módulo ou classe o método pertence. Isso é possível?
Thomthom 10/11/12

@thomthom Sim, isso é possível, você pode chamar self.class.name para ver o nome da classe
Thorin

Excelente uso de regex como um índice de string! Também pode usarcaller[0][/`(.*)'/,1]
aks

1
Isso não parece funcionar no Rails 5.2.1. No controlador Rails, isso retorna "block in make_lambda". Eu acho que isso é apenas para Ruby.
dcangulo

164

No Ruby 2.0.0, você pode usar:

caller_locations(1,1)[0].label

É muito mais rápido que a solução Ruby 1.8+:

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

Será incluído backportsquando receber a hora (ou uma solicitação de recebimento!).


Vale a pena notar que isso não está disponível no Rubinius.
Max

1
se você estiver usando o alavanca, você deve ignorar o rastreamento da alavanca que parece ... não parece haver uma solução padrão para isso.
dtc

6
Agora parece que está caller_locations[0].labelno Ruby 2.2.0, caso contrário, você sempre terá send_actionresultado.
brcebn

1
como podemos obter apenas o método de aplicativo de chamada e ignorar a chamada de estruturas?
Matrix

31

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

Edit : Minha resposta estava dizendo para usar, __method__mas eu estava errado, ele retorna o nome do método atual.


1
@OswaldoFerreira Obrigado, encontrei no SO em outra resposta em algum lugar #
Dorian

5
Isso é incorreto, ele retorna método atual, não o método que chamou o método atual ...
thrice801

1
Funciona como um encanto. Também parece ser muito mais rápido que os métodos anteriores à 2.0.
precisa saber é o seguinte

21

eu uso

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

4
Qual é a vantagem disso em relação à abordagem da DigitalRoss?
Andrew Grimm

2
Mais limpo e preciso. Em vez de fazer a pesquisa, use um método de matriz para dividir caracteres indesejados com base na posição (que pode estar incorreta).
New Alexandria

2
Por que não usar simplesmente o chamador [0] [/ `(. *) '/, 1]? Eu não sou um guru sobre expressões regulares, mas parece funcionar.
Collimarco

7
@ collimarco Contanto que a String não contenha uma 'além da que você está procurando (e presumo que não possa), o resultado será o mesmo, com certeza. No entanto, [^']*terá um desempenho melhor, pois o mecanismo regex deixará de tentar corresponder a essa parte a expressão no momento em que atingir uma '(sua versão será finalizada e, em seguida, retornará porque não encontrou uma 'no final). A diferença é bastante insignificante nesse caso, é claro, mas é um bom hábito evitar .em regexes sempre que possível.
Thor84no

4

E se

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

Muito mais limpo.


3

Em vez disso, você pode escrevê-lo como função de biblioteca e fazer uma chamada sempre que necessário. O código é o seguinte:

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 acionar o método do módulo acima, você precisa chamar assim: caller = CallChain.caller_method

referência de código de


1
Um link para uma solução em potencial é sempre bem-vindo, mas adicione contexto ao link para que seus colegas usuários tenham uma idéia do que é e por que está lá. Sempre cite a parte mais relevante de um link importante, caso o site de destino esteja inacessível ou fique permanentemente offline. Leve em conta que ser pouco mais que um link para um site externo é uma possível razão para Por que e como algumas respostas são excluídas? .
Xavi López

@ XaviLópez ter atualizado a resposta, plz corrigir se estou fazendo de errado ou somthing enganado ... thnx para o tipo sugestão :)
Amit karsale

1
Obrigado por melhorar sua resposta. Infelizmente, não tenho conhecimento suficiente sobre Ruby para poder comentar adequadamente sobre este post, mas a resposta parece boa agora. Eu removi meu voto negativo. Boa sorte :-)
Xavi López

2

Para ver as informações do chamador e do destinatário em qualquer idioma, seja ruby, java ou python, você sempre desejaria examinar o rastreamento da pilha. Em algumas linguagens, como Rust e C ++, há opções integradas no compilador para ativar algum tipo de mecanismo de criação de perfil que você pode exibir durante o tempo de execução. Eu acredito que existe um para Ruby chamado ruby-prof.

E, como mencionado acima, você pode procurar na pilha de execução por ruby. Essa pilha de execução é uma matriz que contém objetos de localização de backtrace.

Basicamente, tudo o que você precisa saber sobre este comando é o seguinte:

chamador (início = 1, comprimento = nulo) → matriz ou nulo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.