我想知道是否可以即时获取源代码方法,以及是否可以获取该方法位于哪个文件中。
喜欢
A.new.method(:a).SOURCE_CODE
A.new.method(:a).FILE
Answers:
用途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"
请注意,对于内置方法,source_location
返回nil
。如果要检查C源代码(玩得开心!),则必须寻找正确的C文件(它们或多或少是按类组织的),并找到rb_define_method
方法的方法(在文件末尾) )。
在Ruby 1.8中,此方法不存在,但是可以使用gem。
到目前为止,没有任何答案显示如何动态显示方法的源代码...
如果您使用John Mair(Pry的制造商)令人敬畏的'method_source'宝石,则实际上非常容易:该方法必须在Ruby中实现(非C),并且必须从文件中加载(而不是irb)。
这是一个使用method_source在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
也可以看看:
source
。这按预期工作。
[1] pry(main)> RSpec.method(:class_exec).source
MethodSource::SourceNotFoundError: Could not locate source for 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
虽然工作正常
没有依赖
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在codde-browing中的文档,使用Pry,您可以使用show-method
来查看方法源,甚至可以看到pry-doc
已安装的一些ruby c源代码。
注意,我们也可以使用pry-doc插件查看C方法(从Ruby Core);我们还展示了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; }
source
方法来说,这是一个好主意Method
。如果它处理了文本,并且在停止打印时输入了new,则更好,因为它已到达方法的结尾。
为此,我创建了“ ri_for” gem
>> require 'ri_for'
>> A.ri_for :foo
...输出源(以及位置,如果您使用的是1.9)。
GL。-r
作为Wrong的一部分,我必须实现类似的功能(获取块的源代码),您可以看到chunk.rb(依赖于Ryan Davis的RubyParser以及如何做的一些有趣的事情)(甚至可以重用代码)源文件含糊代码)。您必须对其进行修改才能使用,Method#source_location
并且可能还要进行一些其他调整,以使其包含或不包含def
。
顺便说一句,我认为Rubinius内置了此功能。出于某种原因,它被排除在MRI(标准的Ruby实现)之外,因此被称为hack。
噢,我喜欢method_source中的一些东西!就像使用eval来判断一个表达式是否有效(并保持含糊不清的源代码行,直到像块一样停止获取解析错误为止)...
String#include?
。到目前为止String.instance_method(:include?).source_location
回报nil
。