2009-06-12 6 views
1

다음과 같은 것을하고 싶습니다 :루비 (Ruby) : 임의의 메소드의 코드를 출력한다.

class String 
    def fancy_thing appendix 
    # Just a trivial example to ensure self and params work. 
    # Pretend this is something complex. 
    self.reverse + appendix 
    end 
end 

# print_method on instance or class should spit out a string 
# containing the actual code for that method 
ft_code = "cob".print_method :fancy_thing 
ft_code = String.print_instance_method :fancy_thing 
    # => "{|appendix| self.reverse + appendix }" * 

# ft_code gets passed around a bit... 

# exec on an object should run code (w/ parameters) as if that code is 
# an instance method on that object (or class method if it's a class) 
"cob".exec(ft_code, '!') #=> "boc!" 

어떻게 print_method와 foo.exec를 하나의 코드로 만들 수 있습니까? 가급적이면, 그들은 임의의 방법으로 작동해야하며, 어디에서 정의되거나 출처를 나타낼 지 미리 알지 못합니다.

  • 예, 방법과 블록이 완전히 동일하지 않다는 것을 알고 있습니다. 그러나 이것은 일반적으로 수확량과 통화량에 더 가깝습니다. 나는 더 나은 해결책을 모른다.
+0

당신이 모두 "속"을 필요가 없습니다 : 맨 위에가는

[편집 2]

, 여기에서 수정 된 버그와 테스트 코드 (그건 당신이 그것을 원) 생각입니다 그 출력물을 인쇄 할 곳. 그 각각의 방법이 무엇을하는지에 대한 질문을 수정하거나 명확히 할 수 있습니까? –

+0

왜 이것을 필요로합니까? –

+0

joshng의 솔루션에 대한 저의 의견에 따라, 목적은 a) irb/콘솔 목적 (디버거가 아닌)과 b) 가능한지보기위한 것입니다. 그들이하는 일에 대한 편집을보십시오. – Sai

답변

7

parse_tree 당신이해야하는 중요한 단계 줄 것이다 :

require 'parse_tree' 
require 'parse_tree_extensions' 
require 'ruby2ruby' 

class Object 
    def method_source(name) 
    (class << self; self; end).instance_method(name).to_ruby 
    end 

    def exec(ruby, *args) 
    code = eval(ruby, binding) 
    code.call(*args) 
    end 
end 

:

http://github.com/seattlerb/parsetree/tree/master

을 나는 이것이 가능한 가장 빠른/hackiest/가장 안전하지 않은 방식으로 그것을 않습니다 생각 나는 이것이 좋은 생각 인 것을 보는 데 어려움을 겪고 있다고 덧붙일 것이다 ... 그러나 당신은 그것을 가지고있다. :-)

[편집]

또한 귀하의 예제가 파열되어 있습니다 : 당신의 'fancy_thing'방법은 인수 (부록)가 필요합니다.

class String 
    def fancy_thing(appendix) 
    reverse << appendix || nil 
    end 
end 

code = "cob".method_source :fancy_thing 
# => "proc {|appendix| reverse << appendix }" * 
"cob".exec code, '!' 
# => "boc!" 
+0

내 의도는 쉬운 디버깅, 메서드 편집 등을 위해 irb/rails 콘솔에 있습니다 (디버거가 적절하지 않을 때). 1.8/1.9에서 * 할 수 있는지 궁금 해서요. ;-) – Sai

+0

OP의 메소드를 수정했습니다. 임원이 제대로 묶여 있는지 확인하기위한 테스트로서 '자기'를 사용하는 것이었지만 정의의 핵심 부분이었습니다. 그러나 실제로는 단지 무작위적인 예입니다. 이제 parse_tree와 ruby2ruby가 magic to_ruby 호출을 어떻게 처리하는지 궁금합니다. 코드를 읽을 필요가있는 것 같습니다. ;) – Sai

+0

당신의 솔루션은 꽤 좋지만 두 가지 경우에 실패합니다. 1) 클래스 메소드; 2) 기본 제공 (예 : "foo".print_method : to_s # => UnsupportedNodeError). 그게 고칠 수 있을지 궁금해. – Sai

0

Ruby 파일을 읽고 메소드 코드를 검색하는 것만으로 구현하기가 쉽지 않습니다. Ruby 1.8에서는 ParseTree와 ruby2ruby를 사용할 수 있습니다. 1.9에서는 어떤 해결책이 있는지 알지 못합니다.

관련 문제