Как я могу получить исходный код метода динамически, а также какой файл этот метод найти в
Я хотел бы знать, могу ли я получить исходный код методом "на лету", и могу ли я получить, в каком файле этот метод.
like
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Ответы
Ответ 1
Используйте source_location
:
class A
def foo
end
end
file, line = A.instance_method(:foo).source_location
# or
file, line = A.new.method(:foo).source_location
puts "Method foo is defined in #{file}, line #{line}"
# => "Method foo is defined in temp.rb, line 2"
Это новичок в Ruby 1.9. Для Ruby 1.8 вы можете использовать этот камень, и я скопирую этот код до backports
, когда получу вторую.
Ответ 2
Ни один из ответов пока не показывает, как отображать исходный код метода на лету...
На самом деле очень просто, если вы используете потрясающий "method_source" камень от Джона Маира (производителя Pry):
Этот метод должен быть реализован в Ruby (не C) и должен быть загружен из файла (не irb).
Вот пример, показывающий исходный код метода в консоли Rails с помощью method_source:
$ rails console
> require 'method_source'
> I18n::Backend::Simple.instance_method(:lookup).source.display
def lookup(locale, key, scope = [], options = {})
init_translations unless initialized?
keys = I18n.normalize_keys(locale, key, scope, options[:separator])
keys.inject(translations) do |result, _key|
_key = _key.to_sym
return nil unless result.is_a?(Hash) && result.has_key?(_key)
result = result[_key]
result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
result
end
end
=> nil
См. также:
Ответ 3
Вот как распечатать исходный код из ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
Ответ 4
Я создал для этого камень "ri_for"
>> require 'ri_for'
>> A.ri_for :foo
... выводит источник (и местоположение, если вы в 1.9).
GL.
-r
Ответ 5
Мне пришлось реализовать подобную функцию (захватить источник блока) как часть Wrong, и вы можете увидеть, как (и возможно, даже повторное использование кода) в chunk.rb (в основе которого лежит RubyParser Райана Дэвиса, а также довольно забавный исходный файл glomming code). Вам нужно будет изменить его, чтобы использовать Method#source_location
и, возможно, настроить другие вещи, чтобы он включал или не включал def
.
Кстати. Я думаю, что у Rubinius встроена эта функция. По какой-то причине она осталась вне MRI (стандартная реализация Ruby), отсюда и этот хак.
Ооо, мне нравятся некоторые вещи в method_source! Как используя eval, чтобы определить, действительно ли выражение является действительным (и продолжайте скрывать исходные строки, пока не прекратите получать ошибки синтаксического анализа, например Chunk)...
Ответ 6
Внутренние методы не имеют расположения источника или источника (например, Integer#to_s
)
require 'method_source'
User.method(:last).source
User.method(:last).source_location
Ответ 7
Без зависимостей
method = SomeConstant.method(:some_method_name)
file_path, line = method.source_location
# puts 10 lines start from the method define
IO.readlines(file_path)[line-1, 10]
Если вы хотите использовать это более удобно, вы можете открыть класс Method
:
# ~/.irbrc
class Method
def source(limit=10)
file, line = source_location
if file && line
IO.readlines(file)[line-1,limit]
else
nil
end
end
end
А затем просто позвоните method.source
С помощью Pry вы можете использовать show-method
для просмотра источника метода, и вы даже можете увидеть некоторый исходный код ruby c с установленным pry-doc
, согласно pry doc в codde-browing
Обратите внимание, что мы также можем просмотреть методы C (из Ruby Core), используя плагин pry-doc; мы также показываем альтернативный синтаксис show-method:
pry(main)> show-method Array#select
From: array.c in Ruby Core (C Method):
Number of lines: 15
static VALUE
rb_ary_select(VALUE ary)
{
VALUE result;
long i;
RETURN_ENUMERATOR(ary, 0, 0);
result = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
rb_ary_push(result, rb_ary_elt(ary, i));
}
}
return result;
}