2016-11-30 5 views
1

言ってやるが、私は次のルビーを持っている:含まれているモデルを含むRubyクラスの "ソースコード"をレンダリングすることはできますか?

module Nameable 
    def name 
    "John" 
    end 
end 

class User 
    include Nameable 
    def email 
    "[email protected]" 
    end 
end 

は、表示、印刷または全体を「ユーザー」の「拡張されたソースコード」を確認する方法はありますか?私は、用語がどうなるかわからないんだけど、「拡張されたソースコード」と私は含ま部品が含まれていますルビー(そうでないAST)内のコード、意味:

class User 
    def name 
    "John" 
    end 

    def email 
    "[email protected]" 
    end 
end 

Bonuspointsを解決します継承された動作のコードを表示することもできます。

+1

これを平坦化することはできません。 'User'は' name'をオーバーライドし、もう存在しない 'super'を呼び出すことができます。 – Stefan

+0

最も簡単な方法 'user.instance_methods'は、メソッド名のリストを表示します。 –

+1

@Stefan。それは問題をより困難にしますが、不可能ではありません。 'super'をエイリアスに置き換え、古い' name'をエイリアスのプライベートメソッドとして保持することができます。 –

答えて

2

method_source gemを使用できます。

require 'method_source' 

def flatten_source_code(klass) 
    excluded_parents = [Kernel, Object, BasicObject] 
    type = klass.instance_of?(Module) ? "module" : "class" 
    puts "#{type} #{klass}" 

    (klass.ancestors-excluded_parents).reverse.each do |ancestor| 
    ancestor.instance_methods(false).each do |method_name| 
     method = ancestor.instance_method(method_name) 
     script, line = method.source_location 
     if script then 
     puts 
     puts " # #{script} (line #{line})" 
     puts method.source 
     else 
     puts 
     puts " # def #{method_name}" 
     puts " # end" 
     end 
    end 
    end 
    puts "end" 
end 

module Nameable 
    def name 
    "John" 
    end 
end 

class User 
    include Nameable 
    def email 
    "[email protected]" 
    end 
end 


flatten_source_code(User) 

puts 

flatten_source_code(Nameable) 

#=> 
# class User 
# 
# # flatten_source_code.rb (line 27) 
# def name 
#  "John" 
# end 
# 
# # flatten_source_code.rb (line 34) 
# def email 
#  "[email protected]" 
# end 
# end 

# module Nameable 
# 
# # flatten_source_code.rb (line 27) 
# def name 
#  "John" 
# end 
# end 

複雑なケースでは完全には機能しませんが、あなたの例では機能します。楽しみのためだけに

、:

John 
prepended [email protected] 

ので、表示されたRubyのコードが有効であると継承の順序を尊重:

module Nameable 
    def name 
    "John" 
    end 

    def email 
    "included [email protected]" 
    end 
end 

module AnotherModule 
    def email 
    "prepended [email protected]" 
    end 
end 

class User 
    include Nameable 
    prepend AnotherModule 
    def email 
    "[email protected]" 
    end 
end 

flatten_source_code(User) 
puts "u = User.new" 
puts "puts u.name" 
puts "puts u.email" 

ruby flatten_source_code.rb | rubyリターンを起動します。しかし、同じメソッドを複数回定義します。

ハッシュを|method_name,method_source|にすることができます。メソッドが古いものを上書きしてsuperを呼び出す場合は、古いメソッドをプライベートold_method_name_from_Module_blablaとして定義し、それに応じてsuperを置き換えます。

関連する問題