Я хотел бы знать, могу ли я получить исходный код методом "на лету", и могу ли я получить, в каком файле этот метод.
like
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Я хотел бы знать, могу ли я получить исходный код методом "на лету", и могу ли я получить, в каком файле этот метод.
like
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Используйте 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, когда получу вторую.
Ни один из ответов пока не показывает, как отображать исходный код метода на лету...
На самом деле очень просто, если вы используете потрясающий "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 
См. также:
Вот как распечатать исходный код из ruby:
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
		Я создал для этого камень "ri_for"
 >> require 'ri_for'
 >> A.ri_for :foo
... выводит источник (и местоположение, если вы в 1.9).
GL. -r
Мне пришлось реализовать подобную функцию (захватить источник блока) как часть Wrong, и вы можете увидеть, как (и возможно, даже повторное использование кода) в chunk.rb (в основе которого лежит RubyParser Райана Дэвиса, а также довольно забавный исходный файл glomming code). Вам нужно будет изменить его, чтобы использовать Method#source_location и, возможно, настроить другие вещи, чтобы он включал или не включал def.
Кстати. Я думаю, что у Rubinius встроена эта функция. По какой-то причине она осталась вне MRI (стандартная реализация Ruby), отсюда и этот хак.
Ооо, мне нравятся некоторые вещи в method_source! Как используя eval, чтобы определить, действительно ли выражение является действительным (и продолжайте скрывать исходные строки, пока не прекратите получать ошибки синтаксического анализа, например Chunk)...
Внутренние методы не имеют расположения источника или источника (например, Integer#to_s)
require 'method_source'
User.method(:last).source
User.method(:last).source_location
		Без зависимостей
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; }