> At Thu, 15 Mar 2001 08:55:43 +0200 Max Ischenko wrote:
> 
> 
> > Is there a tool which can read Ruby code and visually (as GIF, PS,
etc.)
> > present it? Like doxygen for C++.
> 
> > I think this can be done without need to wrote parser because of great
> > Ruby's introspection facilities. With help of something like graphviz
> > www.research.att.com/sw/tools/graphviz
> 
> I crafted simple walker-drawer in an hour:
> #!/usr/bin/env ruby
> # Attempt to create drawer
> 
> class Drawer
>    def drawClasses(root)
>       name = 'classes'
>       title = "Classdiagram"
>       file = name + '.dot'
>       f = File.open(file, 'w')
>       f.puts("digraph #{title} {")
>       ObjectSpace.each_object(root) {|x|
>          if x and x.name and x.superclass
>             # dont draw SystemCallError, it clutters all space
>             next if x.superclass.name == 'SystemCallError'
>             f.puts "#{x.superclass.name} -> \"#{x.name}\"" 
>          end
>       }
>       f.puts("}")
>       f.close
>       system("dot -Tps -o #{name}.ps #{file}")
>    end
> end
> 
> d = Drawer.new
> d.drawClasses(Class)
> 

Although it's nice, here's an alternative. The program prints the 
current class hierarchy in a nice formatted way. The code is refactored
so it should be pretty easy to understand. 


<CODE>

  # 
  # (C) Copyrighted by Paul Pladijs
  # Created on: 2001-03-21, Wednesday
  # Version: 00.01.01
  #
  
 
  class ClassHierarchyPrinter
  
    private
  
    def initialize
      @hierarchy = {}
      @dept = 0
      compute_hierarchy
    end
  
    def get_all_objects
      object_list = []
      ObjectSpace.each_object { |x| object_list << x}
      object_list = object_list.delete_if { |x| x.type != Class}
    end
  
    def init_hierarchy
      @hierarchy = {}
      get_all_objects ().each { |obj|
        @hierarchy[obj] = []
      }
      nil
    end
  
    def construct_hierarchy
      get_all_objects ().each { |x|
        base = x.superclass
        @hierarchy[base] << x unless base.nil?
      }
      nil
    end
  
    def compute_hierarchy
      init_hierarchy
      construct_hierarchy
    end
  
    def get_dept_indent
      result = ""
      unless @dept.zero?
        (1...@dept).each { result += '| '}
        result += '|-'
      end
      result
    end
  
    public
    
    attr_reader :hierarchy
  
    def re_compute
      compute_hierarchy
    end
  
    def print_hierarchy (root = Object, out = $stdout)
      out.print get_dept_indent, root, "\n"
      @dept += 1
      subclasses = @hierarchy[root].sort { |a, b| a.to_s <=> b.to_s}
      subclasses.each { |obj|
        print_hierarchy (obj)
      }
      @dept -= 1
    end
    
  end
  
  
  
  ################
  # Main Program #
  ################
  
  
  c = ClassHierarchyPrinter.new
  c.print_hierarchy 
  
</CODE>

Remark that the ClassHierarchyPrinter class is also included in 
the output-tree, but I guess this is no problem.


Regards,
Paul.