호출 방법의 이름을 얻는 방법?


161

Ruby에서 메소드 내에서 호출 메소드 이름을 찾는 방법이 있습니까?

예를 들면 다음과 같습니다.

class Test
  def self.foo
    Fooz.bar
  end
end

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



"루비에서 현재 실행 된 메소드의 이름을 가져옵니다."의 복제본이 아닙니다. 이 질문은 현재 메소드의 이름이 아닌 호출 메소드의 이름을 묻습니다.
웨인 콘래드

답변:


210
puts caller[0]

아니면 ...

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


10
호출 메소드의 이름을 제공하지만 메소드가 속한 모듈이나 클래스에 대한 표시는 제공하지 않습니다. 가능합니까?
thomthom

@thomthom 네, 가능합니다. self.class.name으로 전화하시면 클래스 이름을보실 수 있습니다
Thorin

문자열 인덱스로 정규 표현식을 잘 사용합니다! caller[0][/`(.*)'/,1]
aks

1
Rails 5.2.1에서는 작동하지 않는 것 같습니다. Rails 컨트롤러에서는 이것을 반환합니다 "block in make_lambda". 나는 이것이 루비 전용이라고 생각한다.
dcangulo

164

Ruby 2.0.0에서는 다음을 사용할 수 있습니다.

caller_locations(1,1)[0].label

그것은이다 훨씬 빠른 루비 1.8 이상 솔루션보다 :

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

backports내가 시간 (또는 풀 요청!)을 얻을 때 포함됩니다 .


Rubinius에서는 사용할 수 없습니다.
Max

1
pry를 사용하는 경우 pry stacktrace를 무시해야합니다 ... 기본 해결책이 아닌 것 같습니다.
dtc

6
이제는 caller_locations[0].label루비 2.2.0 에있는 것 같습니다. 그렇지 않으면 항상 send_action결과를
얻습니다

1
우리는 어떻게 콜 앱 메소드 만 얻고 프레임 워크 호출을 무시할 수 있습니까?
Matrix

31

사용 caller_locations(1,1)[0].label(루비> = 2.0)

편집 : 내 대답에 사용 __method__하려고했지만 잘못되었습니다. 현재 메서드 이름을 반환합니다.


1
@OswaldoFerreira 감사합니다. 다른 곳에서 답변을 찾았습니다
Dorian

5
이것은 정확하지 않습니다. 현재 메소드를 호출 한 메소드가 아니라 현재 메소드를 리턴합니다.
thrice801

1
매력처럼 작동합니다. 또한 2.0 이전의 방법보다 훨씬 빠른 것 같습니다.
Dr.Strangelove

21

나는 사용한다

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

4
DigitalRoss 접근 방식에 비해이 점의 장점은 무엇입니까?
Andrew Grimm

2
더 깨끗하고 정확합니다. 검색하는 대신 배열 방법을 사용하여 위치에 따라 원하지 않는 문자를 나눕니다 (올바르지 않을 수 있음).
새로운 Alexandria

2
단순히 호출자 [0] [/`(. *) '/, 1]를 사용하지 않는 이유는 무엇입니까? 나는 정규 표현식에 대한 전문가가 아니지만 효과가있는 것 같습니다.
collimarco

7
@collimarco String '이 찾고 있는 것 이상을 포함하지 않는 한 (그리고 그것을 할 수 없다고 가정하면) 결과는 동일합니다. 그러나 [^']*정규식 엔진이 해당 부분에 도달하는 순간 그 표현과 일치하는 것을 멈추려 고 할 때 성능이 향상됩니다 '(버전이 끝까지 가고 끝 부분을 찾지 못했기 때문에 역 추적 '합니다). 물론이 경우에는 그 차이를 무시할 수 있지만 .가능한 경우 정규 표현식에서 피하는 것이 좋습니다.
Thor84no

4

어때요?

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

훨씬 더 깨끗한 imo.


3

대신 라이브러리 함수로 작성하여 필요할 때마다 호출 할 수 있습니다. 코드는 다음과 같습니다.

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

위의 모듈 메소드를 트리거하려면 다음과 같이 호출해야합니다. caller = CallChain.caller_method

의 코드 참조


1
잠재적 인 솔루션에 대한 링크는 언제나 환영하지만 링크 주위에 컨텍스트추가 하여 동료 사용자가 그 이유와 그 이유를 알 수 있도록하십시오. 대상 사이트에 도달 할 수 없거나 영구적으로 오프라인 상태가되는 경우 항상 중요한 링크의 가장 관련성있는 부분을 인용하십시오. 되는 것을 고려 보다 외부 사이트로의 링크보다 거의 것은 에 관해서는 가능한 이유가 왜 그리고 어떻게 어떤 답변 삭제입니까? .
Xavi López

@ XaviLópez는 답변을 업데이트했습니다. plz는 잘못하고 있거나 잘못 생각하는 경우 수정합니다 ... 종류 제안을 위해 thnx :)
amit karsale

1
답변을 개선해 주셔서 감사합니다. 불행히도, 나는이 게시물에 대해 적절하게 언급 할 수있는 루비에 대한 지식이 충분하지 않지만 지금은 그 대답이 괜찮아 보입니다. downvote를 제거했습니다. 최고의 행운 :-)
사비 로페즈

2

루비, 자바 또는 파이썬이든, 어떤 언어로든 발신자 및 수신자 정보를 보려면 항상 스택 추적을보고 싶을 것입니다. Rust 및 C ++와 같은 일부 언어에는 런타임 중에 볼 수있는 일종의 프로파일 링 메커니즘을 설정하기 위해 컴파일러에 내장 된 옵션이 있습니다. 나는 ruby-prof라는 루비가 존재한다고 믿습니다.

위에서 언급했듯이 루비의 실행 스택을 살펴볼 수 있습니다. 이 실행 스택은 역 추적 위치 객체를 포함하는 배열입니다.

기본적으로이 명령에 대해 알아야 할 것은 다음과 같습니다.

발신자 (시작 = 1, 길이 = 없음) → 배열 또는 없음

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.