为什么 UnboundMethod 没有实例方法 source ,因为它有 source location ?我该如何破解呢?
Why doesn't UnboundMethod have the instance method `source` since it has `source location`? And how can I hack this?
为什么 UnboundMethod
没有实例方法 source
因为它有 source location
?我该如何破解呢? Does ruby's metaprogramming don't good enough to do this?(Does ruby's metaprogramming suck?) 如果是这样,你能为我推荐一个更好的语言来完成这个吗?
这是一个例子来解释我的问题:
# test.rb
class TestClass
def test_m_a
puts "test_m_a path: #{path}"
end
def test_m_b
puts "test_m_b path: #{path}"
end
instance_methods(false).each do |name|
puts "source_location: #{instance_method(name).source_location}"
method_source_code_ar = instance_method(name).source.split("\n")
method_source_code_ar.insert(1, 'path = __method__.to_s.split("_").join("/")')
method_source_code_ar.insert(-2, 'puts "#{__method__} end"')
method_source_code = method_source_code_ar.join("\n")
eval(method_source_code)
end
end
运行在撬:
➜ ~
➜ ~ pry
[1] pry(main)> require './test.rb'
source_location: ["/home/yanying/test.rb", 5]
source_location: ["/home/yanying/test.rb", 8]
=> true
[2] pry(main)> TestClass.new.test_m_a
test_m_a path: test/m/a
test_m_a end
=> nil
[3] pry(main)> TestClass.new.test_m_b
test_m_b path: test/m/b
test_m_b end
=> nil
[4] pry(main)>
运行 在 irb:
~ irb
2.1.5 :001 > require './test.rb'
source_location: ["/home/yanying/test.rb", 5]
NoMethodError: undefined method `source' for #<UnboundMethod: TestClass#test_m_a>
from /home/yanying/test.rb:13:in `block in <class:TestClass>'
from /home/yanying/test.rb:12:in `each'
from /home/yanying/test.rb:12:in `<class:TestClass>'
from /home/yanying/test.rb:4:in `<top (required)>'
from /home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from (irb):1
from /home/yanying/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
2.1.5 :002 >
这是参考的原始程序:
出于调试目的记住源位置,以便生成包含有用信息的堆栈跟踪。
不记住来源(因为会浪费大量内存);只有编译后的代码是。你可以看到 that with RubyVM::InstructionSequence.disasm(instance_method(name))
.
在 Pry 中为你工作的 source
是由 Pry 实现的(好吧,实际上是由 Pry 所依赖的 method_source
gem):它读取位于 [=14 的文件=],然后在 source_location
行找到表达式。
编辑:你怎么破解这个?
$ gem install method_source
$ irb -r method_source
> puts Method.instance_method(:source).source
# => def source
# MethodSource.source_helper(source_location, defined?(name) ? name : inspect)
# end
Does ruby's metaprogramming suck?
不,它实际上是最好的。但是您通常不需要获取源代码。如果您描述了您正在尝试解决的实际问题,那么可能有更好的方法来完成您正在尝试做的事情。
为什么 UnboundMethod
没有实例方法 source
因为它有 source location
?我该如何破解呢? Does ruby's metaprogramming don't good enough to do this?(Does ruby's metaprogramming suck?) 如果是这样,你能为我推荐一个更好的语言来完成这个吗?
这是一个例子来解释我的问题:
# test.rb
class TestClass
def test_m_a
puts "test_m_a path: #{path}"
end
def test_m_b
puts "test_m_b path: #{path}"
end
instance_methods(false).each do |name|
puts "source_location: #{instance_method(name).source_location}"
method_source_code_ar = instance_method(name).source.split("\n")
method_source_code_ar.insert(1, 'path = __method__.to_s.split("_").join("/")')
method_source_code_ar.insert(-2, 'puts "#{__method__} end"')
method_source_code = method_source_code_ar.join("\n")
eval(method_source_code)
end
end
运行在撬:
➜ ~
➜ ~ pry
[1] pry(main)> require './test.rb'
source_location: ["/home/yanying/test.rb", 5]
source_location: ["/home/yanying/test.rb", 8]
=> true
[2] pry(main)> TestClass.new.test_m_a
test_m_a path: test/m/a
test_m_a end
=> nil
[3] pry(main)> TestClass.new.test_m_b
test_m_b path: test/m/b
test_m_b end
=> nil
[4] pry(main)>
运行 在 irb:
~ irb
2.1.5 :001 > require './test.rb'
source_location: ["/home/yanying/test.rb", 5]
NoMethodError: undefined method `source' for #<UnboundMethod: TestClass#test_m_a>
from /home/yanying/test.rb:13:in `block in <class:TestClass>'
from /home/yanying/test.rb:12:in `each'
from /home/yanying/test.rb:12:in `<class:TestClass>'
from /home/yanying/test.rb:4:in `<top (required)>'
from /home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from (irb):1
from /home/yanying/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
2.1.5 :002 >
这是参考的原始程序:
出于调试目的记住源位置,以便生成包含有用信息的堆栈跟踪。
不记住来源(因为会浪费大量内存);只有编译后的代码是。你可以看到 that with RubyVM::InstructionSequence.disasm(instance_method(name))
.
在 Pry 中为你工作的 source
是由 Pry 实现的(好吧,实际上是由 Pry 所依赖的 method_source
gem):它读取位于 [=14 的文件=],然后在 source_location
行找到表达式。
编辑:你怎么破解这个?
$ gem install method_source
$ irb -r method_source
> puts Method.instance_method(:source).source
# => def source
# MethodSource.source_helper(source_location, defined?(name) ? name : inspect)
# end
Does ruby's metaprogramming suck?
不,它实际上是最好的。但是您通常不需要获取源代码。如果您描述了您正在尝试解决的实际问题,那么可能有更好的方法来完成您正在尝试做的事情。