DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Simple Ruby Script To Create A .dot File From Rails Models
Save the script below railmodel, then try:
railmodel myrailapp | dot -Tpng > myrailmodel.png
where myrailapp, is the complete directory to one of your rails applications. You will of course have to have graphviz installed (http://www.research.att.com/sw/tools/graphviz/).
#!/bin/ruby -w
require 'active_support'
Relation = Struct.new("Relation", :parent, :child, :relation, :options)
#
def gendot(dir)
nodes = []
relations = []
cur_model = ''
base = File.join(dir, 'app', 'models')
Dir.new(base).each do |fname|
next if fname =~ /^\./
File.open(File.join(base,fname)) do |handle|
handle.each do |line|
if line =~ /class\s+(\S+)\s+<\s+(\S*)/
if $2 != "ActiveRecord::Base"
cur_model = "$1 [shape=box,bottomlabel=\"#{$2}\"]"
else
cur_model = $1
end
nodes << cur_model
elsif line =~ /^\s*([A-Za-z_0-9]+)\s*(.*)/
#puts " Found >>#{$1}<< >>#{$2}<< >>#{line.strip}<<"
relation = $1
opts = $2.split(/\s*[,:]+\s*/).delete_if {|elem| elem.empty? }
#puts " Found #{relation} - #{opts.inspect} -- >>#{$2}<< >>#{line.strip}<<"
case relation
when 'has_one'
relations << Relation.new(cur_model, opts[0].classify, relation)
when 'has_many'
relations << Relation.new(cur_model, opts[0].classify, relation, 'arrowhead' => 'inv')
when 'has_and_belongs_to_many'
relations << Relation.new(cur_model, opts[0].classify, 'fix', 'dir' => 'both')
when 'belongs_to'
relations << Relation.new(cur_model, opts[0].classify, relation, 'label' => "belongs_to", "style" => "dashed")
when 'acts_as_tree'
relations << Relation.new(cur_model, cur_model, relation)
else
#puts " *** NOT FOUND #{$1} ***"
end
end
end
end
end
# look for duplicate has_and_belongs_to_many relations
relations.each do |a|
if a.relation == "fix"
a.relation = "has_and_belongs_to_many"
STDERR.puts "Checking #{a.inspect}"
relations.delete_if { |b| b.relation == "fix" && a.parent == b.child && a.child = b.parent }
end
end
puts "digraph simple {"
puts nodes.join("\n")
relations.each do |rel|
#rel.label = rel.relation unless rel.label
print "#{rel.parent}->#{rel.child}"
rel.options = {} unless rel.options
if rel.options
rel.options['label'] = rel.relation unless rel.options['label']
print " ["
opts = rel.options.map do |k,v|
k + "=" +
if k == "label"
%Q["#{v}"]
else
v
end
end
print opts.join(",")
print "]"
end
puts
end
puts "}"
end
if $0 == __FILE__
dir = ARGV[0]
gendot(dir)
end





