p = Proc.new{ puts 'ok' }
是否可以在proc中看到ruby代码?
inspect
返回内存位置:
puts p.inspect
#<Proc:0x007f9e42980b88@(irb):2>
Ruby 1.9.3
答案 0 :(得分:8)
看一下sourcify gem:
proc { x + y }.to_source
# >> "proc { (x + y) }"
答案 1 :(得分:5)
您的意思是原始源代码还是其字节码表示?
对于前者,您可以使用标准Proc的方法source_location
p.source_location
=> ["test.rb", 21]
并阅读相应的代码行。
对于后者,RubyVM :: InstructionSequence及其类方法可以反汇编:
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"
答案 2 :(得分:4)
不,没有办法在Ruby中这样做。
某些Ruby实现可能有也可能没有特定于实现的获取源代码的方法。
您还可以尝试使用Proc#source_location
查找Proc
中定义的文件,然后解析该文件以查找源代码。但是,如果Proc
未在文件中定义(例如,如果它是使用eval
动态定义的),或者源文件不再存在,那么这将不起作用,例如:因为你正在运行程序的AOT编译版本。
所以,简短的回答是:不,没有办法。 长期的答案是:有些方法可能会或可能不会有效,取决于太多的因素,甚至开始使这项工作可靠。
这甚至没有考虑到{em}已经拥有 Ruby源代码的Proc
,因为它们是在本机代码中定义的。
答案 3 :(得分:2)
如果将proc定义到文件中,U可以获取proc的文件位置然后序列化它,然后在反序列化之后使用该位置再次返回到proc
反序列化后proc_location_array = proc.source_location
:
file_name = proc_location_array [0]
line_number = proc_location_array [1]
proc_line_code = IO.readlines(file_name)[line_number - 1]
proc_hash_string = proc_line_code [proc_line_code.index(&#34; {&#34;).. proc_line_code.length]
proc = eval(&#34; lambda#{proc_hash_string}&#34;)
答案 4 :(得分:0)
尽管还是一个老问题,我还是想分享自己的想法。
您可以使用Pry gem并得到如下结果:
[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' }
此外,如果要从Rails上下文中使用它,则可以输入:
::Kernel.binding.pry
在您的控制器或模型中,以及
- require 'pry'; binding.pry
在您想要启动调试的位置。
在测试中,我使用组合,首先在顶部使用require 'pry'
,然后在需要的地方使用::Kernel.binding.pry
。
参考文献: