2009-06-12 20 views
1

我想這樣做如下:紅寶石:打印(上下文和exec)任意方法的代碼

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

那些地方打印輸出。你可以修改/澄清這些方法中每一種的作用嗎? – 2009-06-12 05:28:00

+0

爲什麼你需要這個? – 2009-06-12 05:31:57

回答

7

parse_tree會給你的關鍵一步,你需要:

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

我覺得這樣做了,在最快/ hackiest /最不安全的可能方式:

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 

我會補充一點,我很難看出這是一個好主意......但是你有它。 :-)

[編輯]

此外請注意您的例子搗毀:你的 'fancy_thing' 方法需要一個參數(附錄)。

[編輯2]

打算過頂,這裏是你的測試代碼修復的bug(的方式,我想你想的話):你不應該在雙方都需要「芯」

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

這不是很容易實現,只需閱讀Ruby文件並搜索方法代碼即可。在Ruby 1.8中,你可以使用ParseTree和ruby2ruby。在1.9中,我不知道任何解決方案。