GraphvizRでRubyのクラス継承図を描いてみる
一番時間がかかったのはMacPortsの入れ直しだった・・・。
require 'rubygems' require 'graphviz_r' class ObjectSpace::GraphvizR attr_accessor :gvr def initialize(name = 'ruby_class') # GraphvizRのインスタンスを生成 @gvr = GraphvizR.new name # グラフの方向を左→右に指定 @gvr.graph[:rankdir => :LR] # ObjectSpaceを使ってすべてのクラスとその親クラスのHashを作る @children = Hash.new ObjectSpace.each_object(Class) do |o| if s = o.superclass (@children[s.to_s] ||= []) << o.to_s end end end # クラス階層に従ってグラフを描く def visit(name) node = escape(name) # []メソッドでノードを作れるので、さらにそのノードの[]メソッドで属性を指定する @gvr[node][:label => name] if @children[name] @children[name].sort.each do |child| next if child.include?(':') # この行を削ると全クラスを含む巨大グラフが・・・ visit(child) # 親クラス→子クラスのエッジを作る @gvr[node] >> @gvr[escape(child)] end end end # クラス名に:が入っているとGraphvizで文法エラーになるので削る def escape(name) name.tr(':', '') end def output(name) visit(name) @gvr.output end end if __FILE__ == $0 ObjectSpace::GraphvizR.new.output('Object') end
ちなみに、Windowsではちゃんと動かすには、入出力をバイナリモードにするよう、GraphvizR本体を修正する必要がある。
201c201 < gv = IO.popen "dot -q -T#{format || 'png'}", "w+" --- > gv = IO.popen "dot -q -T#{format || 'png'}", "w+b" 214c214 < File.open(filename || "#{@name}.#{format || 'png'}", "w+") do |file| --- > File.open(filename || "#{@name}.#{format || 'png'}", "w+b") do |file|