method_source
method_source copied to clipboard
Shouldn't `source` method work with `eval` ?
This is a test case to demonstrate what I mentioned in the title:
#!/usr/bin/env ruby
# test.rb
class TestClass
source = <<-EOF
def test_m
"test_m here"
end
EOF
eval(source)
end
[1] pry(main)> require './test.rb'
=> true
[2] pry(main)> TestClass.new.test_m
=> "test_m here"
[3] pry(main)> m = TestClass.new.method :test_m
=> #<Method: TestClass#test_m>
[4] pry(main)> m.source
MethodSource::SourceNotFoundError: Could not load source for : No such file or directory @ rb_sysopen - (eval)
from /home/yanying/.rvm/gems/ruby-2.1.5/gems/method_source-0.8.2/lib/method_source.rb:55:in `rescue in lines_for'
[5] pry(main)> m.source_location
=> ["(eval)", 1]
[6] pry(main)>
There's no way to read source code from eval.
The live_ast gem does something like this. Here's a quick proof-of-concept to work with method_source:
require 'method_source'
@store = {}
def store src
key = "(eval@#{src.hash})"
@store[key] = src
key
end
def source_eval src, bnd, *rest
key = store src
eval src, bnd, key, 1
end
source_eval <<-END, binding
def bar
puts 'FOO'
end
def foo
puts 'BAR'
end
END
f = method(:foo)
key, line = *f.source_location
p MethodSource.expression_at(@store[key], line)
A real implementation would need to override eval and use binding_of_caller to automate this.