royw-railroad_xing 0.5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +340 -0
- data/ChangeLog +91 -0
- data/README +155 -0
- data/bin/railroad +52 -0
- data/lib/railroad/aasm_diagram.rb +88 -0
- data/lib/railroad/app_diagram.rb +109 -0
- data/lib/railroad/ar_model.rb +102 -0
- data/lib/railroad/controllers_diagram.rb +81 -0
- data/lib/railroad/diagram_graph.rb +139 -0
- data/lib/railroad/dm_model.rb +148 -0
- data/lib/railroad/framework_factory.rb +35 -0
- data/lib/railroad/merb_framework.rb +45 -0
- data/lib/railroad/model_factory.rb +25 -0
- data/lib/railroad/models_diagram.rb +86 -0
- data/lib/railroad/options_struct.rb +169 -0
- data/lib/railroad/rails_framework.rb +45 -0
- data/railroad_xing.gemspec +32 -0
- metadata +70 -0
data/bin/railroad
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# RailRoad - RoR diagrams generator
|
4
|
+
# http://railroad.rubyforge.org
|
5
|
+
#
|
6
|
+
# RailRoad generates models and controllers diagrams in DOT language
|
7
|
+
# for a Rails application.
|
8
|
+
#
|
9
|
+
# Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
|
10
|
+
#
|
11
|
+
# This program is free software; you can redistribute it and/or modify
|
12
|
+
# it under the terms of the GNU General Public License as published by
|
13
|
+
# the Free Software Foundation; either version 2 of the License, or
|
14
|
+
# (at your option) any later version.
|
15
|
+
#
|
16
|
+
|
17
|
+
APP_NAME = "railroad"
|
18
|
+
APP_HUMAN_NAME = "RailRoad"
|
19
|
+
APP_VERSION = [0,5,0]
|
20
|
+
COPYRIGHT = "Copyright (C) 2007-2008 Javier Smaldone"
|
21
|
+
|
22
|
+
require 'railroad/options_struct'
|
23
|
+
require 'railroad/models_diagram'
|
24
|
+
require 'railroad/controllers_diagram'
|
25
|
+
require 'railroad/aasm_diagram'
|
26
|
+
|
27
|
+
options = OptionsStruct.new
|
28
|
+
|
29
|
+
options.parse ARGV
|
30
|
+
|
31
|
+
old_dir = Dir.pwd
|
32
|
+
|
33
|
+
Dir.chdir(options.root) if options.root != ''
|
34
|
+
|
35
|
+
if options.command == 'models'
|
36
|
+
diagram = ModelsDiagram.new options
|
37
|
+
elsif options.command == 'controllers'
|
38
|
+
diagram = ControllersDiagram.new options
|
39
|
+
elsif options.command == 'aasm'
|
40
|
+
diagram = AasmDiagram.new options
|
41
|
+
else
|
42
|
+
STDERR.print "Error: You must supply a command\n" +
|
43
|
+
" (try #{APP_NAME} -h)\n\n"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
diagram.generate
|
48
|
+
|
49
|
+
Dir.chdir(old_dir)
|
50
|
+
|
51
|
+
diagram.print
|
52
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# RailRoad - RoR diagrams generator
|
2
|
+
# http://railroad.rubyforge.org
|
3
|
+
#
|
4
|
+
# Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
|
5
|
+
# See COPYING for more details
|
6
|
+
|
7
|
+
# AASM code provided by Ana Nelson (http://ananelson.com/)
|
8
|
+
|
9
|
+
# Dec 2008 - Roy Wright
|
10
|
+
# enable only for Rails as AASM is a Rails plugin
|
11
|
+
|
12
|
+
require 'railroad/app_diagram'
|
13
|
+
|
14
|
+
# Diagram for Acts As State Machine
|
15
|
+
class AasmDiagram < AppDiagram
|
16
|
+
|
17
|
+
def initialize(options)
|
18
|
+
#options.exclude.map! {|e| e = "app/models/" + e}
|
19
|
+
super options
|
20
|
+
@graph.diagram_type = 'Models'
|
21
|
+
# Processed habtm associations
|
22
|
+
@habtm = []
|
23
|
+
end
|
24
|
+
|
25
|
+
# Process model files
|
26
|
+
def generate
|
27
|
+
STDERR.print "Generating AASM diagram\n" if @options.verbose
|
28
|
+
files = Dir.glob("app/models/**/*.rb")
|
29
|
+
files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
|
30
|
+
files -= @options.exclude
|
31
|
+
files.each do |f|
|
32
|
+
process_class extract_class_name(f).constantize
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Load model classes
|
39
|
+
def load_classes
|
40
|
+
unless @framework.name == 'Rails'
|
41
|
+
print_error 'AASM diagrams only supported for Rails'
|
42
|
+
raise LoadError.new
|
43
|
+
end
|
44
|
+
begin
|
45
|
+
disable_stdout
|
46
|
+
files = Dir.glob("app/models/**/*.rb")
|
47
|
+
files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
|
48
|
+
files -= @options.exclude
|
49
|
+
files.each {|m| require m }
|
50
|
+
enable_stdout
|
51
|
+
rescue LoadError
|
52
|
+
enable_stdout
|
53
|
+
print_error "model classes"
|
54
|
+
raise
|
55
|
+
end
|
56
|
+
end # load_classes
|
57
|
+
|
58
|
+
# Process a model class
|
59
|
+
def process_class(current_class)
|
60
|
+
|
61
|
+
STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
|
62
|
+
|
63
|
+
# Only interested in acts_as_state_machine models.
|
64
|
+
return unless current_class.respond_to?'states'
|
65
|
+
|
66
|
+
node_attribs = []
|
67
|
+
node_type = 'aasm'
|
68
|
+
|
69
|
+
current_class.states.each do |state_name|
|
70
|
+
state = current_class.read_inheritable_attribute(:states)[state_name]
|
71
|
+
node_shape = (current_class.initial_state === state_name) ? ", peripheries = 2" : ""
|
72
|
+
node_attribs << "#{current_class.name.downcase}_#{state_name} [label=#{state_name} #{node_shape}];"
|
73
|
+
end
|
74
|
+
@graph.add_node [node_type, current_class.name, node_attribs]
|
75
|
+
|
76
|
+
current_class.read_inheritable_attribute(:transition_table).each do |event_name, event|
|
77
|
+
event.each do |transition|
|
78
|
+
@graph.add_edge [
|
79
|
+
'event',
|
80
|
+
current_class.name.downcase + "_" + transition.from.to_s,
|
81
|
+
current_class.name.downcase + "_" + transition.to.to_s,
|
82
|
+
event_name.to_s
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end # process_class
|
87
|
+
|
88
|
+
end # class AasmDiagram
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# RailRoad - RoR diagrams generator
|
2
|
+
# http://railroad.rubyforge.org
|
3
|
+
#
|
4
|
+
# Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
|
5
|
+
# See COPYING for more details
|
6
|
+
#
|
7
|
+
# Dec 2008 - Roy Wright
|
8
|
+
# added FrameworkFactory to support multiple application frameworks
|
9
|
+
|
10
|
+
require 'railroad/diagram_graph'
|
11
|
+
require 'railroad/framework_factory'
|
12
|
+
|
13
|
+
# Root class for RailRoad diagrams
|
14
|
+
class AppDiagram
|
15
|
+
|
16
|
+
def initialize(options)
|
17
|
+
@options = options
|
18
|
+
@graph = DiagramGraph.new
|
19
|
+
@graph.show_label = @options.label
|
20
|
+
|
21
|
+
STDERR.print "Loading application environment\n" if @options.verbose
|
22
|
+
load_environment
|
23
|
+
|
24
|
+
STDERR.print "Loading application classes\n" if @options.verbose
|
25
|
+
load_classes
|
26
|
+
end
|
27
|
+
|
28
|
+
# Print diagram
|
29
|
+
def print
|
30
|
+
if @options.output
|
31
|
+
old_stdout = STDOUT.dup
|
32
|
+
begin
|
33
|
+
STDOUT.reopen(@options.output)
|
34
|
+
rescue
|
35
|
+
STDERR.print "Error: Cannot write diagram to #{@options.output}\n\n"
|
36
|
+
exit 2
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if @options.xmi
|
41
|
+
STDERR.print "Generating XMI diagram\n" if @options.verbose
|
42
|
+
STDOUT.print @graph.to_xmi
|
43
|
+
else
|
44
|
+
STDERR.print "Generating DOT graph\n" if @options.verbose
|
45
|
+
STDOUT.print @graph.to_dot
|
46
|
+
end
|
47
|
+
|
48
|
+
if @options.output
|
49
|
+
STDOUT.reopen(old_stdout)
|
50
|
+
end
|
51
|
+
end # print
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Prevents Rails application from writing to STDOUT
|
56
|
+
def disable_stdout
|
57
|
+
@old_stdout = STDOUT.dup
|
58
|
+
STDOUT.reopen(PLATFORM =~ /mswin/ ? "NUL" : "/dev/null")
|
59
|
+
end
|
60
|
+
|
61
|
+
# Restore STDOUT
|
62
|
+
def enable_stdout
|
63
|
+
STDOUT.reopen(@old_stdout)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# Print error when loading Rails application
|
68
|
+
def print_error(type)
|
69
|
+
STDERR.print "Error loading #{type}.\n (Are you running " +
|
70
|
+
"#{APP_NAME} on the application's root directory?)\n\n"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Load Rails application's environment
|
74
|
+
def load_environment
|
75
|
+
begin
|
76
|
+
disable_stdout
|
77
|
+
@framework = FrameworkFactory.getFramework
|
78
|
+
raise LoadError.new if @framework.nil?
|
79
|
+
@graph.migration_version = @framework.migration_version
|
80
|
+
enable_stdout
|
81
|
+
rescue LoadError
|
82
|
+
enable_stdout
|
83
|
+
print_error "application environment"
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# is the given class a subclass of the application controller?
|
89
|
+
def is_application_subclass?(klass)
|
90
|
+
@framework.is_application_subclass?(klass)
|
91
|
+
end
|
92
|
+
|
93
|
+
# get the controller's files returning the application controller first in returned array
|
94
|
+
def get_controller_files(options)
|
95
|
+
@framework.get_controller_files(options)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Extract class name from filename
|
99
|
+
def extract_class_name(filename)
|
100
|
+
@framework.extract_class_name(filename)
|
101
|
+
end
|
102
|
+
|
103
|
+
# convert the give string to a constant
|
104
|
+
def constantize(str)
|
105
|
+
@framework.constantize(str)
|
106
|
+
end
|
107
|
+
|
108
|
+
end # class AppDiagram
|
109
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# The "model" used to interact with ActiveRecord models.
|
2
|
+
#
|
3
|
+
# Dec 2008 - Roy Wright
|
4
|
+
# created class an refactored logic from models_diagram.rb
|
5
|
+
#
|
6
|
+
class AR_Model
|
7
|
+
def initialize(klass, options)
|
8
|
+
@klass = klass
|
9
|
+
# Processed habtm associations
|
10
|
+
@habtm = []
|
11
|
+
end
|
12
|
+
|
13
|
+
# return an Array of attribute (column) "name:type" strings for the
|
14
|
+
# model.
|
15
|
+
# if @options.hide_magic is asserted, then remove some standard
|
16
|
+
# attribute names from the array.
|
17
|
+
# if @options.hide_types is asserted, then the returned strings are
|
18
|
+
# just the names "name".
|
19
|
+
def attributes
|
20
|
+
attribs = []
|
21
|
+
|
22
|
+
if @options.hide_magic
|
23
|
+
# From patch #13351
|
24
|
+
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
25
|
+
magic_fields = [
|
26
|
+
"created_at", "created_on", "updated_at", "updated_on",
|
27
|
+
"lock_version", "type", "id", "position", "parent_id", "lft",
|
28
|
+
"rgt", "quote", "template"
|
29
|
+
]
|
30
|
+
magic_fields << @klass.table_name + "_count" if @klass.respond_to? 'table_name'
|
31
|
+
content_columns = @klass.content_columns.select {|c| ! magic_fields.include? c.name}
|
32
|
+
else
|
33
|
+
content_columns = @klass.content_columns
|
34
|
+
end
|
35
|
+
|
36
|
+
content_columns.each do |a|
|
37
|
+
content_column = a.name
|
38
|
+
content_column += ' :' + a.type.to_s unless @options.hide_types
|
39
|
+
attribs << content_column
|
40
|
+
end
|
41
|
+
attribs
|
42
|
+
end
|
43
|
+
|
44
|
+
# is the model abstract?
|
45
|
+
def abstract?
|
46
|
+
@klass.abstract_class?
|
47
|
+
end
|
48
|
+
|
49
|
+
# return the model edges (relationships)
|
50
|
+
def edges
|
51
|
+
found_edges = []
|
52
|
+
# Process class associations
|
53
|
+
associations = @klass.reflect_on_all_associations
|
54
|
+
if @options.inheritance && ! @options.transitive
|
55
|
+
superclass_associations = @klass.superclass.reflect_on_all_associations
|
56
|
+
|
57
|
+
associations = associations.select{|a| ! superclass_associations.include? a}
|
58
|
+
# This doesn't works!
|
59
|
+
# associations -= current_class.superclass.reflect_on_all_associations
|
60
|
+
end
|
61
|
+
associations.each do |a|
|
62
|
+
found_edges << process_association(@klass.name, a)
|
63
|
+
end
|
64
|
+
found_edges.compact
|
65
|
+
end
|
66
|
+
|
67
|
+
# is the model meaningful?
|
68
|
+
def meaningful?
|
69
|
+
(@klass.superclass != ActiveRecord::Base) && (@klass.superclass != Object)
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Process a model association
|
75
|
+
def process_association(class_name, assoc)
|
76
|
+
STDERR.print "\t\tProcessing model association #{assoc.name.to_s}\n" if @options.verbose
|
77
|
+
|
78
|
+
assoc_type = nil
|
79
|
+
# Skip "belongs_to" associations
|
80
|
+
unless assoc.macro.to_s == 'belongs_to'
|
81
|
+
# Only non standard association names needs a label
|
82
|
+
assoc_class_name = (assoc.class_name.respond_to? 'underscore') ? assoc.class_name.underscore.singularize.camelize : assoc.class_name
|
83
|
+
if assoc_class_name == assoc.name.to_s.singularize.camelize
|
84
|
+
assoc_name = ''
|
85
|
+
else
|
86
|
+
assoc_name = assoc.name.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
if assoc.macro.to_s == 'has_one'
|
90
|
+
assoc_type = 'one-one'
|
91
|
+
elsif assoc.macro.to_s == 'has_many' && (! assoc.options[:through])
|
92
|
+
assoc_type = 'one-many'
|
93
|
+
else # habtm or has_many, :through
|
94
|
+
return if @habtm.include? [assoc.class_name, class_name, assoc_name]
|
95
|
+
assoc_type = 'many-many'
|
96
|
+
@habtm << [class_name, assoc.class_name, assoc_name]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
assoc_type.nil? ? nil : [assoc_type, class_name, assoc_class_name, assoc_name]
|
100
|
+
end # process_association
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# RailRoad - RoR diagrams generator
|
2
|
+
# http://railroad.rubyforge.org
|
3
|
+
#
|
4
|
+
# Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
|
5
|
+
# See COPYING for more details
|
6
|
+
#
|
7
|
+
# Dec 2008
|
8
|
+
# minor isolation from framework
|
9
|
+
|
10
|
+
require 'railroad/app_diagram'
|
11
|
+
|
12
|
+
# RailRoad controllers diagram
|
13
|
+
class ControllersDiagram < AppDiagram
|
14
|
+
|
15
|
+
def initialize(options)
|
16
|
+
#options.exclude.map! {|e| "app/controllers/" + e}
|
17
|
+
super options
|
18
|
+
@graph.diagram_type = 'Controllers'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Process controller files
|
22
|
+
def generate
|
23
|
+
STDERR.print "Generating controllers diagram\n" if @options.verbose
|
24
|
+
|
25
|
+
files = get_controller_files(@options)
|
26
|
+
files.each do |f|
|
27
|
+
class_name = extract_class_name(f)
|
28
|
+
process_class constantize(class_name)
|
29
|
+
end
|
30
|
+
end # generate
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Load controller classes
|
35
|
+
def load_classes
|
36
|
+
begin
|
37
|
+
disable_stdout
|
38
|
+
# ApplicationController must be loaded first
|
39
|
+
files = get_controller_files(@options)
|
40
|
+
files.each {|c| require c }
|
41
|
+
enable_stdout
|
42
|
+
rescue LoadError
|
43
|
+
enable_stdout
|
44
|
+
print_error "controller classes"
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
end # load_classes
|
48
|
+
|
49
|
+
# Proccess a controller class
|
50
|
+
def process_class(current_class)
|
51
|
+
|
52
|
+
STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
|
53
|
+
|
54
|
+
if @options.brief
|
55
|
+
@graph.add_node ['controller-brief', current_class.name]
|
56
|
+
elsif current_class.is_a? Class
|
57
|
+
# Collect controller's methods
|
58
|
+
node_attribs = {:public => [],
|
59
|
+
:protected => [],
|
60
|
+
:private => []}
|
61
|
+
current_class.public_instance_methods(false).sort.each { |m|
|
62
|
+
node_attribs[:public] << m
|
63
|
+
} unless @options.hide_public
|
64
|
+
current_class.protected_instance_methods(false).sort.each { |m|
|
65
|
+
node_attribs[:protected] << m
|
66
|
+
} unless @options.hide_protected
|
67
|
+
current_class.private_instance_methods(false).sort.each { |m|
|
68
|
+
node_attribs[:private] << m
|
69
|
+
} unless @options.hide_private
|
70
|
+
@graph.add_node ['controller', current_class.name, node_attribs]
|
71
|
+
elsif @options.modules && current_class.is_a?(Module)
|
72
|
+
@graph.add_node ['module', current_class.name]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generate the inheritance edge (only for ApplicationControllers)
|
76
|
+
if @options.inheritance && is_application_subclass?(current_class)
|
77
|
+
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
78
|
+
end
|
79
|
+
end # process_class
|
80
|
+
|
81
|
+
end # class ControllersDiagram
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# RailRoad - RoR diagrams generator
|
2
|
+
# http://railroad.rubyforge.org
|
3
|
+
#
|
4
|
+
# Copyright 2007-2008 - Javier Smaldone (http://www.smaldone.com.ar)
|
5
|
+
# See COPYING for more details
|
6
|
+
#
|
7
|
+
# Dec 2008 - Roy Wright
|
8
|
+
# minor isolation from framework
|
9
|
+
|
10
|
+
# RailRoad diagram structure
|
11
|
+
class DiagramGraph
|
12
|
+
attr_accessor :migration_version
|
13
|
+
def initialize
|
14
|
+
@migration_version = nil
|
15
|
+
@diagram_type = ''
|
16
|
+
@show_label = false
|
17
|
+
@nodes = []
|
18
|
+
@edges = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_node(node)
|
22
|
+
@nodes << node
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_edge(edge)
|
26
|
+
@edges << edge
|
27
|
+
end
|
28
|
+
|
29
|
+
def diagram_type= (type)
|
30
|
+
@diagram_type = type
|
31
|
+
end
|
32
|
+
|
33
|
+
def show_label= (value)
|
34
|
+
@show_label = value
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# Generate DOT graph
|
39
|
+
def to_dot
|
40
|
+
return dot_header +
|
41
|
+
@nodes.uniq.map{|n| dot_node n[0], n[1], n[2]}.join +
|
42
|
+
@edges.uniq.map{|e| dot_edge e[0], e[1], e[2], e[3]}.join +
|
43
|
+
dot_footer
|
44
|
+
end
|
45
|
+
|
46
|
+
# Generate XMI diagram (not yet implemented)
|
47
|
+
def to_xmi
|
48
|
+
STDERR.print "Sorry. XMI output not yet implemented.\n\n"
|
49
|
+
return ""
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# Build DOT diagram header
|
55
|
+
def dot_header
|
56
|
+
result = "digraph #{@diagram_type.downcase}_diagram {\n" +
|
57
|
+
"\tgraph[overlap=false, splines=true]\n"
|
58
|
+
result += dot_label if @show_label
|
59
|
+
return result
|
60
|
+
end
|
61
|
+
|
62
|
+
# Build DOT diagram footer
|
63
|
+
def dot_footer
|
64
|
+
return "}\n"
|
65
|
+
end
|
66
|
+
|
67
|
+
# Build diagram label
|
68
|
+
def dot_label
|
69
|
+
buf = []
|
70
|
+
buf << "\t_diagram_info [shape=\"plaintext\", "
|
71
|
+
buf << "label=\"#{@diagram_type} diagram\\l"
|
72
|
+
buf << "Date: #{Time.now.strftime "%b %d %Y - %H:%M"}\\l"
|
73
|
+
unless @migration_version.nil?
|
74
|
+
buf << "Migration version: #{@migration_version}\\l"
|
75
|
+
end
|
76
|
+
buf << "Generated by #{APP_HUMAN_NAME} #{APP_VERSION.join('.')}"
|
77
|
+
buf << "\\l\", fontsize=14]\n"
|
78
|
+
buf.join('')
|
79
|
+
end
|
80
|
+
|
81
|
+
# Build a DOT graph node
|
82
|
+
def dot_node(type, name, attributes=nil)
|
83
|
+
case type
|
84
|
+
when 'model'
|
85
|
+
options = 'shape=Mrecord, label="{' + name + '|'
|
86
|
+
options += attributes.join('\l')
|
87
|
+
options += '\l}"'
|
88
|
+
when 'model-brief'
|
89
|
+
options = ''
|
90
|
+
when 'class'
|
91
|
+
options = 'shape=record, label="{' + name + '|}"'
|
92
|
+
when 'class-brief'
|
93
|
+
options = 'shape=box'
|
94
|
+
when 'controller'
|
95
|
+
options = 'shape=Mrecord, label="{' + name + '|'
|
96
|
+
public_methods = attributes[:public].join('\l')
|
97
|
+
protected_methods = attributes[:protected].join('\l')
|
98
|
+
private_methods = attributes[:private].join('\l')
|
99
|
+
options += public_methods + '\l|' + protected_methods + '\l|' +
|
100
|
+
private_methods + '\l'
|
101
|
+
options += '}"'
|
102
|
+
when 'controller-brief'
|
103
|
+
options = ''
|
104
|
+
when 'module'
|
105
|
+
options = 'shape=box, style=dotted, label="' + name + '"'
|
106
|
+
when 'aasm'
|
107
|
+
# Return subgraph format
|
108
|
+
return "subgraph cluster_#{name.downcase} {\n\tlabel = #{quote(name)}\n\t#{attributes.join("\n ")}}"
|
109
|
+
end # case
|
110
|
+
return "\t#{quote(name)} [#{options}]\n"
|
111
|
+
end # dot_node
|
112
|
+
|
113
|
+
# Build a DOT graph edge
|
114
|
+
def dot_edge(type, from, to, name = '')
|
115
|
+
options = name != '' ? "label=\"#{name}\", " : ''
|
116
|
+
case type
|
117
|
+
when 'one-one'
|
118
|
+
#options += 'taillabel="1"'
|
119
|
+
options += 'arrowtail=odot, arrowhead=dot, dir=both'
|
120
|
+
when 'one-many'
|
121
|
+
#options += 'taillabel="n"'
|
122
|
+
options += 'arrowtail=crow, arrowhead=dot, dir=both'
|
123
|
+
when 'many-many'
|
124
|
+
#options += 'taillabel="n", headlabel="n", arrowtail="normal"'
|
125
|
+
options += 'arrowtail=crow, arrowhead=crow, dir=both'
|
126
|
+
when 'is-a'
|
127
|
+
options += 'arrowhead="none", arrowtail="onormal"'
|
128
|
+
when 'event'
|
129
|
+
options += "fontsize=10"
|
130
|
+
end
|
131
|
+
return "\t#{quote(from)} -> #{quote(to)} [#{options}]\n"
|
132
|
+
end # dot_edge
|
133
|
+
|
134
|
+
# Quotes a class name
|
135
|
+
def quote(name)
|
136
|
+
'"' + name.to_s + '"'
|
137
|
+
end
|
138
|
+
|
139
|
+
end # class DiagramGraph
|