Як отримати назву методу виклику?


161

чи є спосіб у Ruby знайти ім'я виклику всередині методу?

Наприклад:

class Test
  def self.foo
    Fooz.bar
  end
end

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



Не дублікат "Отримати ім'я поточно виконаного методу в Ruby." Це питання запитує ім'я виклику методу, а не ім'я поточного методу.
Уейн Конрад

Відповіді:


210
puts caller[0]

а може ...

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

5
Так, дивіться Kernel # calller
DigitalRoss

10
Це дає ім'я виклику методу, але він не дає жодних вказівок, до якого модуля чи класу належить метод. Це можливо?
thomthom

@thomthom Так, це можливо, ви можете зателефонувати self.class.name, щоб побачити ім'я класу
Thorin

Відмінне використання регулярного вираження в якості рядкового індексу! Також можна використовуватиcaller[0][/`(.*)'/,1]
акс

1
Схоже, це не працює в Rails 5.2.1. У контролері Rails це повертається "block in make_lambda". Я думаю, це лише для Рубі.
dcangulo

164

У Ruby 2.0.0 ви можете використовувати:

caller_locations(1,1)[0].label

Це набагато швидше, ніж рішення Ruby 1.8+:

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

Буду включатися, backportsколи я отримаю час (або запит на тягу!).


Варто зазначити, що в Рубінія це недоступно.
Макс

1
якщо ур, використовуючи pry, вам доведеться ігнорувати стек трафіку, як здається ... для цього не здається рішення за замовчуванням.
dtc

6
Тепер, здається, caller_locations[0].labelна Ruby 2.2.0. У вас завжди send_actionрезультат
brcebn

1
як ми можемо отримати лише метод виклику додатків і ігнорувати виклик фреймворків?
Матриця

31

Використовувати caller_locations(1,1)[0].label(для рубіну> = 2,0)

Редагувати : у моїй відповіді було сказати, що використовувати, __method__але я помилявся, він повертає поточну назву методу


1
@OswaldoFerreira Спасибі, знайшов його на SO в іншій відповіді десь
Доріан

5
Це неправильно, він повертає поточний метод, а не метод, який викликав поточний метод ...
тричі801

1
працює як шарм. Також здається, що це набагато швидше, ніж попередні методи 2.0.
Dr.Strangelove

21

я використовую

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

4
Яка перевага цього підходу в порівнянні з DigitalRoss?
Ендрю Грімм

2
Чистіше і точніше. Замість того, щоб здійснювати пошук, використовуючи метод масиву, щоб розділити небажані символи на основі позиції (що може бути неправильним).
Нова Олександрія

2
Чому б просто не використовувати абонента [0] [/ `(. *) '/, 1]? Я не гуру щодо регулярних виразів, але це, здається, працює.
collimarco

7
@collimarco До тих пір, поки в рядку не буде 'більше того, що ви шукаєте (і я припускаю, що не може), результат буде точно таким же. Однак він [^']*буде працювати краще, оскільки двигун регулярного випромінювання перестане намагатися співставити цю частину виразу в момент, коли вона досягне '(ваша версія піде до кінця, а потім повернеться назад, тому що вона не знайшла в 'кінці). Різниця є досить незначною у цьому випадку, звичайно, але це корисна увага уникати .регексів, де це можливо.
Thor84no


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 оновили відповідь, плз виправте, чи я роблю неправильно, чи
щось помилилося

1
Дякуємо, що покращили вашу відповідь. На жаль, у мене недостатньо знань про Рубі, щоб можна було правильно коментувати цю публікацію, але відповідь зараз виглядає нормально. Я видалив свій потік. Найкраща удача :-)
Хаві Лопес

2

Для того, щоб побачити інформацію про виклику та виклику будь-якою мовою, будь то рубін або java чи пітон, ви завжди хочете переглянути слід стека. У деяких мовах, таких як Rust і C ++, є вбудовані в компілятор параметри, щоб увімкнути якийсь механізм профілювання, який ви можете переглядати під час виконання. Я вірю, що існує для Рубі, яку називають рубіном-проф.

І як було сказано вище, ви можете заглянути в стек виконання для рубіну. Цей стек виконання - це масив, що містить об'єкти розташування заднім числом.

По суті, все, що вам потрібно знати про цю команду, полягає в наступному:

абонент (старт = 1, довжина = нуль) → масив або нуль

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.