Недавно у нас возникла проблема, когда после серии коммитов серверный процесс не запускался. Теперь мы были хорошими мальчиками и девочками и бегали rake test
после каждой регистрации, но из-за некоторых странностей в загрузке библиотеки Rails это происходило только тогда, когда мы запускали ее непосредственно из Mongrel в производственном режиме.
Я отследил ошибку, и это произошло из-за того, что новый драгоценный камень Rails переписал метод в классе String способом, который нарушил одно узкое использование в коде Rails времени выполнения.
В любом случае, если коротко, есть ли способ, во время выполнения, спросить Ruby, где был определен метод? Что-то подобное whereami( :foo )
возвращается /path/to/some/file.rb line #45
? В этом случае, сказать мне, что он был определен в классе String, было бы бесполезно, потому что он был перегружен какой-то библиотекой.
Я не могу гарантировать, что источник живет в моем проекте, поэтому поиск 'def foo'
не обязательно даст мне то, что мне нужно, не говоря уже о том, есть ли у меня их много def foo
, иногда я не знаю до времени выполнения, какой из них я могу использовать.
источник
Ответы:
Это действительно поздно, но вот как вы можете найти, где определен метод:
http://gist.github.com/76951
Если вы используете Ruby 1.9+, вы можете использовать
source_location
Обратите внимание, что это не будет работать на все, как нативный скомпилированный код. Класс Method также имеет несколько полезных функций, таких как Method # owner, который возвращает файл, в котором определен метод.
РЕДАКТИРОВАТЬ: Также см.
__file__
И__line__
и примечания для REE в другом ответе, они тоже удобны. - РГисточник
owner
метод2.method(:crime)
?Fixnum
method_missing
. Так что если у вас есть класс модуля или предка сclass_eval
илиdefine_method
внутриmethod_missing
, то этот метод не будет работать.На самом деле вы можете пойти немного дальше, чем решение выше. Для Ruby 1.8 Enterprise Edition, есть
__file__
и__line__
методы наMethod
случаях:Для Ruby 1.9 и выше есть
source_location
(спасибо Джонатан!):источник
__file__
и__line__
на любомMethod
экземпляре класса, экс:method(:method).__file__
.m.__file__
иm.__line__
были заменены наm.source_location
.Я опаздываю к этой теме и удивляюсь, что никто не упомянул
Method#owner
.источник
Method#parameters
.Копирование моего ответа из более нового аналогичного вопроса, который добавляет новую информацию к этой проблеме.
В Ruby 1.9 есть метод с именем source_location :
Это было перенесено в 1.8.7 этим драгоценным камнем:
Таким образом, вы можете запросить метод:
А затем спросите
source_location
об этом методе:Это вернет массив с именем файла и номером строки. Например, для
ActiveRecord::Base#validates
этого возвращается:Для классов и модулей Ruby не предлагает встроенную поддержку, но есть отличный Gist, основанный
source_location
на возврате файла для данного метода или первого файла для класса, если метод не был указан:В действии:
На компьютерах Mac с установленным TextMate также появляется редактор в указанном месте.
источник
Это может помочь, но вам придется кодировать его самостоятельно. Вставлено из блога:
http://scie.nti.st/2008/9/17/making-methods-immutable-in-ruby
источник
Если вы можете вызвать сбой метода, вы получите обратную трассировку, которая точно скажет вам, где он находится.
К сожалению, если вы не можете разбить его, вы не можете узнать, где он был определен. Если вы попытаетесь изменить метод, перезаписав его или переопределив, любой сбой произойдет из-за перезаписанного или переопределенного метода, и он не будет использоваться.
Полезные способы сбоя методов:
nil
где это запрещено, - в большинстве случаев метод будет вызыватьArgumentError
или всегда присутствоватьNoMethodError
в нулевом классе.источник
require 'ruby-debug'; debugger
в код, куда хотите его вставить .Может быть,
#source_location
может помочь найти источник метода.например:
Возвращение
ИЛИ
Возвращение
источник
Очень поздний ответ :) Но более ранние ответы мне не помогли
источник
nil
?nil
.»Вы могли бы сделать что-то вроде этого:
foo_finder.rb:
Затем убедитесь, что foo_finder загружен первым с чем-то вроде
(Я только перепутал с рельсами, так что я точно не знаю, но я думаю, что есть способ начать это примерно так.)
Это покажет вам все переопределения String # foo. Немного метапрограммирования вы можете обобщить для любой функции, которую захотите. Но он должен быть загружен ПЕРЕД файлом, который фактически выполняет переопределение.
источник
Вы всегда можете получить информацию о том, где вы находитесь, используя
caller()
.источник