Ruby 为什么';t UnboundMethod是否具有实例方法“source”,因为它具有“source location”?我怎样才能破解这个?
为什么Ruby 为什么';t UnboundMethod是否具有实例方法“source”,因为它具有“source location”?我怎样才能破解这个?,ruby,metaprogramming,Ruby,Metaprogramming,为什么取消绑定方法没有实例方法源,因为它有源位置?我怎样才能破解这个?ruby的元编程还不够好吗?(ruby的元编程糟糕吗?) 下面是一个例子来解释我的问题: # 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 d
取消绑定方法
没有实例方法源
,因为它有源位置
?我怎样才能破解这个?ruby的元编程还不够好吗?(ruby的元编程糟糕吗?)
下面是一个例子来解释我的问题:
# 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 >
~irb
2.1.5:001>要求“/test.rb”
来源位置:[“/home/yanying/test.rb”,5]
NoMethodError:的未定义方法“source”#
from/home/yanying/test.rb:13:in'block in'
from/home/yanying/test.rb:12:in'each'
from/home/yanying/test.rb:12:in`'
from/home/yanying/test.rb:4:in`'
from/home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site\u ruby/2.1.0/rubygems/core\u ext/kernel\u require.rb:54:in'require'
from/home/yanying/.rvm/rubies/ruby-2.1.5/lib/ruby/site\u ruby/2.1.0/rubygems/core\u ext/kernel\u require.rb:54:in'require'
来自(irb):1
from/home/yanying/.rvm/rubies/ruby-2.1.5/bin/irb:11:in`'
2.1.5 :002 >
这是参考的原始程序:
出于调试目的,会记住源位置,因此可以使用有用的信息生成堆栈跟踪 源不被记住(因为它会浪费大量内存);只有编译后的代码是正确的。您可以通过
RubyVM::InstructionSequence.disasm(实例\方法(名称))
看到这一点
在Pry中为您工作的source
由Pry实现(实际上是通过Pry所依赖的method\u source
gem):它读取source\u位置的文件
,然后在source\u位置
行中找到表达式
编辑:你怎么能破解这个
$ 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
ruby的元编程糟糕吗
不,它实际上是最好的。但是你通常不需要得到来源。如果您描述了您试图解决的实际问题,那么可能有更好的方法来解决您试图解决的问题。我的实际问题与示例基本相同。我需要在之前
之后添加
钩住类方法,不想涉及“实例变量”。请检查:谢谢,添加gemmethod\u source
解决了我的问题。