2011-12-29 12 views
1

実行時編集のいくつかの魔法に触発されたソースコードRubyでソースコードを取得するには?

私はそれをRubyでやりたいです。私は方法/クラスからソースコードを得ることができないように見える それを行う方法はありますか?

私はここのサンプルソースコードを記述します。

def helloworld n 
    "hello #{n}" 
end 

o = Kernel.method :helloword 

Kernel.define_singleton_method o.name do |n| 
    eval o.source_code.sub('hello', 'hello world') 
end 

helloworld 'halida' #=> 'hello world halida' 
+0

はStackOverflowの上で同様の質問を参照してくださいすることができますhttp://stackoverflow.com/questions/4740684/ruby-get-source-codeまたはhttp://stackoverflow.com/questions/3393096/how -c-i-get-source-code-of-a-methods-dynamic-and-the-file-this-mまたはhttp://stackoverflow.com/questions/4719649/ruby-print-source -codeまたはhttp://stackoverflow.com/questions/1164903/find-the-source-of-eval-code ... – mliebelt

答えて

0

あなたは、コードの一部の文字列表現を取得し、それを編集し、Rubyの変更を再評価することを期待することはできません。あなたが望むものに近い何かをする唯一の方法は、ParseTreeを使ってソースのs式を取得し、Ruby2Rubyを編集してルビコードの文字列を生成することです。それらの文字列にdef ...endを追加し、それを使ってevalを呼び出します。

実際の状況では、これは難しく、エラーが発生しやすくなりません。しかし私は他の方法を知らない。

注:ParseTreeはRuby 1.8でのみ動作します。

+0

OK、私はこの種の魔法を投げるためにlispを使用します。 – linjunhalida

+0

あなたは絶対にソースコードの文字列表現。クラスメソッドには '.method.source'、インスタンスメソッドには' .instance_method.source'を使用してください。文字列を編集して再適用するには、クラスを開いてメソッドを再定義し、新しい文字列に 'eval'を使用します。 –

+0

'class_eval'と' instance_eval'も参照してください。 –

0

method_source gemをご覧ください。これはpry REPLのshow-methodコマンドで使用されています。

このgemのように見えるのは、標準のMethod#source_location(Ruby 1.9で利用可能)を使用してメソッドを探し、そのソースコードを取得することです。明らかに、動的に定義されたメソッドとCメソッドでは機能しません。詳細については、docsを参照してください。

0

Rubyでメソッドのソースコードを簡単に取得できます。

次架空のクラスを想像してみて:

class Klass 
    def self.foo 
    :foo 
    end 

    def bar 
    :bar 
    end 
end 

あなたが見ることができるように、このクラスは2つのメソッドがあります

  • クラスメソッド.fooという
#barインスタンスメソッドを

.method.instance_methodを使用してプログラムにアクセスしてくださいmatically:

m1 = Klass.method :foo 
=> #<Method: Klass.foo> 

m2 = Klass.instance_method :bar 
=> #<UnboundMethod: Klass#bar> 

あなたはそれらのソースコードを表示する.sourceメソッドを使用することができます。

puts m1.source 
    def self.foo 
    :foo 
    end 
=> nil 

puts m2.source 
    def self.bar 
    :bar 
    end 
=> nil 

Rubyはオープンクラスと動的ローディングを持っているので、あなたはまた、実行時に変更する方法を追加したり、 することができます。ただ、クラスを再オープンし、メソッドを再定義:

Klass.foo 
=> :foo 

class Klass 
    def self.foo 
    :foobar 
    end 
end 

Klass.foo 
=> :footer 

以前クラスで定義された他の方法は影響を受けません。

Klass.bar 
=> :bar 

WARNING:実行時にクラスの振る舞いを再定義(も "と呼ばれますMonkey Patching ") は非常に強力なツールですが、やはりやや危険です。現在のバージョンのRuby は、これを「改良」と呼ぶより制御された方法をサポートしています。

あなたはlearn more about using refinements here

関連する問題