Ruby 如何动态获取方法的源代码以及该方法位于哪个文件中

Ruby 如何动态获取方法的源代码以及该方法位于哪个文件中,ruby,Ruby,我想知道我是否可以在运行中获取一个方法的源代码,以及是否可以获取该方法所在的文件 像 使用源位置: 注意,对于内置方法,source_location返回nil。如果想查看C源代码,请玩得开心!,您必须查找正确的C文件,它们或多或少是按类组织的,并在文件末尾找到该方法的rb_define_方法 在Ruby 1.8中,这种方法不存在,但您可以使用。我为此创建了用于gem的ri_ >> require 'ri_for' >> A.ri_for :foo 。。。如果使用1

我想知道我是否可以在运行中获取一个方法的源代码,以及是否可以获取该方法所在的文件

使用源位置:

注意,对于内置方法,source_location返回nil。如果想查看C源代码,请玩得开心!,您必须查找正确的C文件,它们或多或少是按类组织的,并在文件末尾找到该方法的rb_define_方法


在Ruby 1.8中,这种方法不存在,但您可以使用。

我为此创建了用于gem的ri_

 >> require 'ri_for'
 >> A.ri_for :foo
。。。如果使用1.9,则输出源和位置

德国劳埃德船级社。
-r

到目前为止,没有一个答案显示如何动态显示方法的源代码

如果您使用Pry制造商John Mair制作的令人敬畏的“method_source”宝石,这其实非常简单: 该方法必须用Ruby而不是C实现,并且必须从文件(而不是irb)加载

下面是一个示例,显示Rails控制台中的方法源代码和方法源代码:

  $ 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 
另见:


我必须实现一个类似的功能,抓取一个块的源代码作为其中的一部分,您可以看到如何甚至重用依赖于Ryan Davis的RubyParser以及一些非常有趣的源文件的代码。您必须修改它以使用Methodsource_location,并可能调整一些其他内容,使其包含或不包含def

顺便说一句,我认为Rubinius内置了这个功能。由于某种原因,它被排除在标准Ruby实现之外,因此出现了这种攻击


哦,我喜欢里面的一些东西!像Chunk一样,不断地对源代码行进行修饰,直到你不再出现解析错误…

下面是如何从ruby打印源代码:

puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])

内部方法没有源或源位置,例如Integerto_

没有依赖关系

如果希望更方便地使用此方法,可以打开方法类:

然后调用method.source

使用Pry,您可以使用show方法查看方法源代码,甚至可以看到一些安装了Pry文档的ruby c源代码,Pry在

注意,我们还可以使用 撬动文档插件;我们还展示了show方法的替代语法:

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;
}

所有这些对我来说都是产生了一个分割错误如何再现seg故障?哪个方法/类?我总是错过Ruby中的这个特性。Lisp可以做到这一点:来自Clojure的源代码。这与预期的一样。我收到以下错误:[1]prymain>RSpec.method:class_exec.source MethodSource::SourceNotFoundError:找不到class_exec的源!from/home/vagrant/.bundle/foo/ruby/2.5.0/gems/method_source-0.9.2/lib/method_source.rb:24:in'source_helper'RSpec.method:to_json.source_location工作得很好,我来自未来,使用ruby 2.6.1!我想要Stringinclude?的源代码?。到目前为止,String.instance\u method:include?.source\u location返回nil。对于method类中的源方法来说,这是个好主意。如果它能处理文本,并在什么时候停止打印,那就更好了,因为它已经到达了方法的末尾。
puts File.read(OBJECT_TO_GET.method(:METHOD_FROM).source_location[0])
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]
# ~/.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
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;
}