可以在proc中看到ruby代码吗?

可以在proc中看到ruby代码吗?,ruby,block,proc,Ruby,Block,Proc,可以在proc中看到ruby代码吗 inspect返回内存位置: p = Proc.new{ puts 'ok' } 放置p.inspect # Ruby 1.9.3看看宝石: 你是指原始源代码还是它的字节码表示 对于前者,您可以使用标准Proc的方法source\u location proc { x + y }.to_source # >> "proc { (x + y) }" 并阅读相应的代码行 对于后者,可以使用RubyVM::InstructionSequence及其

可以在proc中看到ruby代码吗

inspect
返回内存位置:

p = Proc.new{ puts 'ok' }
放置p.inspect
#
Ruby 1.9.3

看看宝石:


你是指原始源代码还是它的字节码表示

对于前者,您可以使用标准Proc的方法
source\u location

proc { x + y }.to_source
# >> "proc { (x + y) }"
并阅读相应的代码行

对于后者,可以使用RubyVM::InstructionSequence及其类方法:

p.source_location
=> ["test.rb", 21]
irb>RubyVM::指令sequence.disasm p
=>“==disasm:
====\n==捕获表\n |捕获类型:重做st:0000 ed:0011 sp:0000
续:0000\n |捕获类型:下一个st:0000 ed:0011 sp:0000续:
0011\n |---------------------------------------------------------------\n
0000跟踪1
(1)\n0002 putself\n0003 putstring \“确定\”\n0005
发送:puts,1,nil,8,\n0011离开\n“

不,在Ruby中无法做到这一点

一些Ruby实现可能有也可能没有特定于实现的获取源代码的方法

您还可以尝试使用
Proc#source_location
查找定义了
Proc
的文件,然后解析该文件以查找源代码。但是,如果文件中没有定义
Proc
(例如,如果它是使用
eval
动态定义的),或者如果源文件不再存在,例如,因为您运行的是AOT编译版本的程序,那么这将不起作用

因此,简单的回答是:不,没有办法。 长话短说的答案是:有些方法有时可能有效,有时也可能无效,这取决于太多的因素,甚至无法开始可靠地工作


这甚至没有考虑到
Proc
s,它们甚至没有Ruby源代码,因为它们是在本机代码中定义的。

如果Proc被定义到一个文件中,你可以获取Proc的文件位置,然后将其序列化,然后在反序列化后使用该位置再次返回到Proc

proc\u位置\u数组=proc.source\u位置

反序列化后:

文件名=过程位置数组[0]

行号=过程位置数组[1]

proc_line_code=IO.readlines(文件名)[行编号-1]

proc_hash_string=proc_line_code[proc_line_code.index(“{”)…proc_line_code.length]

proc=eval(“lambda{proc_hash_string}”)


虽然这是个老问题,但我还是想和大家分享我的想法

您可以使用Pry gem,最终得到如下结果:

irb> RubyVM::InstructionSequence.disasm p
=> "== disasm: <RubyVM::InstructionSequence:block in irb_binding@(irb)>
=====\n== catch table\n| catch type: redo   st: 0000 ed: 0011 sp: 0000
cont: 0000\n| catch type: next   st: 0000 ed: 0011 sp: 0000 cont:
0011\n|------------------------------------------------------------------------\n
0000 trace            1                                               
(   1)\n0002 putself          \n0003 putstring        \"ok\"\n0005 
send             :puts, 1, nil, 8, <ic:0>\n0011 leave            \n"
在控制器或模型中,以及

::Kernel.binding.pry
在视图中,开始调试

在测试中,我使用了一个组合,首先在顶部
需要'pry'
,然后在需要的地方
::Kernel.binding.pry

参考资料:


RubyVM
是YARV的非标准扩展。它不是Ruby语言规范的一部分。MRI没有它,Rubinius没有它,MagLev没有它,JRuby没有它,IronRuby没有它。我不希望依赖只在单个Ruby实现上工作的东西。@JörgWMittag所以MRI被困在1.8和Ruby 1.9不是正式的实现吗?@JörgWMittag另一方面,我一般同意不依赖特定的实现功能,但有时很难保持。是的,MRI停留在1.8。MRI不打算支持Ruby的任何更高版本。Matz自己很久以前就停止了MRI的工作,他现在专注于n YARV(由Koichi Sasada编写)和最近的MRuby(由他自己编写的ISO Ruby实现).Ruby 1.9不是一个实现,它是一种语言。Ruby 1.9没有正式的实现,有一个语言规范,每个满足该规范的实现都和其他实现一样正式。其中一些实现是YARV、MacRuby、JRuby和Rubinius。sourcify对Ruby 1之后的任何事情都有很大的警告.9.我很幸运使用了Ruby 2.1.2的源方法gem(pry将其作为依赖项包含在内,因此在我们的测试基础架构中我需要它)。我在这里有一个详细的答案:
[11] pry> p = Proc.new{ puts 'ok' }
=> #<Proc:0x007febe00e6360@(pry):23>

[12] pry> show-source p

From: (pry)
Number of lines: 1

p = Proc.new{ puts 'ok' }
::Kernel.binding.pry
- require 'pry'; binding.pry