2009-06-12 7 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

あなたは両方に「コブ」を必要はありませんその出力を印刷する場所。それらのメソッドのそれぞれが何をするかについての質問を修正/明確にすることはできますか? –

+0

なぜこれが必要ですか? –

+0

joshngの解説には、a)irb /コンソール用(デバッガ本体外)とb)可能かどうかを確認する目的があります。編集内容を参照してください。 – Sai

答えて

7

parse_treeはあなたが必要です重要なステップを与えます私はこれが良い考え方であることを見るのが難しいと付け加えます...しかし、あなたはそれを持っています。 :-)

[編集]

また、あなたの例が逮捕されていることに注意してください:あなたの 'fancy_thing' メソッドは、引数(付録)が必要です。

[編集2]

トップの上に行くには、ここで修正されたバグとテストコード(私はあなたがそれを望んでいたと思う方法が)です:

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のメソッドを修正しました。その定義のポイントの一部は、execが正しくバインドされていることを確認するためのテストとして 'self'を使用することでした。しかし、実際にはランダムな例です。 今、私はparse_treeとruby2rubyがmagic to_rubyをどのように呼び出すのだろうかと思います。私は彼らのコードを読む必要があるように見えます。 ;) – Sai

+0

あなたのソリューションはかなり良いですが、2つの理由で失敗します。 1)クラスメソッド。 2)組み込み関数(例: "foo" .print_method:to_s#=> UnsupportedNodeError)。それが修正可能かどうか疑問に思います。 – Sai

0

これは、Rubyファイルを読み込んでメソッドコードを検索するだけでは簡単に実装できません。 Ruby 1.8では、ParseTreeとruby2rubyを使用できます。 1.9では、何の解決策もわかりません。

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 

:可能な最速/ hackiest /最も安全でない方法で、私はこれはそれをしないと思います

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

関連する問題