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的元编程糟糕吗


不,它实际上是最好的。但是你通常不需要得到来源。如果您描述了您试图解决的实际问题,那么可能有更好的方法来解决您试图解决的问题。

我的实际问题与示例基本相同。我需要在之前
之后添加
钩住类方法,不想涉及“实例变量”。请检查:谢谢,添加gem
method\u source
解决了我的问题。