factorylabs-railroad 0.6.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,145 @@
1
+ = RailRoad
2
+
3
+ RailRoad generates models and controllers diagrams in DOT language for a
4
+ Rails application.
5
+
6
+
7
+ = Usage
8
+
9
+ Run RailRoad on the Rails application's root directory. You can redirect its
10
+ output to a .dot file or pipe it to the dot or neato utilities to produce a
11
+ graphic. Model diagrams are intended to be processed using dot and
12
+ controller diagrams are best processed using neato.
13
+
14
+ railroad [options] command
15
+
16
+ == Options
17
+
18
+ Common options:
19
+ -b, --brief Generate compact diagram
20
+ (no attributes nor methods)
21
+ -e, --exclude file1[,fileN] Exclude given files
22
+ -i, --inheritance Include inheritance relations
23
+ -l, --label Add a label with diagram information
24
+ (type, date, migration, version)
25
+ -o, --output FILE Write diagram to file FILE
26
+ -v, --verbose Enable verbose output
27
+ (produce messages to STDOUT)
28
+
29
+ Models diagram options:
30
+ -a, --all Include all models
31
+ (not only ActiveRecord::Base derived)
32
+ --hide-magic Hide magic field names
33
+ --hide-types Hide attributes type
34
+ -j, --join Concentrate edges
35
+ -m, --modules Include modules
36
+ -p, --plugins-models Include plugins models
37
+ -t, --transitive Include transitive associations
38
+ (through inheritance)
39
+
40
+ Controllers diagram options:
41
+ --hide-public Hide public methods
42
+ --hide-protected Hide protected methods
43
+ --hide-private Hide private methods
44
+
45
+ Other options:
46
+ -h, --help Show this message
47
+ --version Show version and copyright
48
+
49
+ == Commands
50
+
51
+ -M, --models Generate models diagram
52
+ -C, --controllers Generate controllers diagram
53
+ -A, --aasm Generate "acts as state machine" diagram
54
+
55
+
56
+ == Examples
57
+
58
+ railroad -o models.dot -M
59
+ Produces a models diagram to the file 'models.dot'
60
+ railroad -a -i -o full_models.dot -M
61
+ Models diagram with all classes showing inheritance relations
62
+ railroad -M | dot -Tsvg > models.svg
63
+ Model diagram in SVG format
64
+ railroad -C | neato -Tpng > controllers.png
65
+ Controller diagram in PNG format
66
+ railroad -h
67
+ Shows usage help
68
+
69
+
70
+ = Processing DOT files
71
+
72
+ To produce a PNG image from model diagram generated by RailRoad you can
73
+ issue the following command:
74
+
75
+ dot -Tpng models.dot > models.png
76
+
77
+ If you want to do the same with a controller diagram, use neato instead of
78
+ dot:
79
+
80
+ neato -Tpng controllers.dot > controllers.png
81
+
82
+ If you want to produce SVG (vectorial, scalable, editable) files, you can do
83
+ the following:
84
+
85
+ dot -Tsvg models.dot > models.svg
86
+ neato -Tsvg controllers.dot > controllers.svg
87
+
88
+ Important: There is a bug in Graphviz tools when generating SVG files that
89
+ cause a text overflow. You can solve this problem editing (with a text
90
+ editor, not a graphical SVG editor) the file and replacing around line 12
91
+ "font-size:14.00;" by "font-size:11.00;", or by issuing the following command
92
+ (see "man sed"):
93
+
94
+ sed -i 's/font-size:14.00/font-size:11.00/g' file.svg
95
+
96
+ Note: For viewing and editing SVG there is an excellent opensource tool
97
+ called Inkscape (similar to Adobe Illustrator. For DOT processing you can
98
+ also use Omnigraffle (on Mac OS X).
99
+
100
+ = RailRoad as a rake task
101
+
102
+ (Thanks to Thomas Ritz, http://www.galaxy-ritz.de ,for the code.)
103
+
104
+ In your Rails application, put the following rake tasks into 'lib/task/diagrams.rake':
105
+
106
+ namespace :doc do
107
+ namespace :diagram do
108
+ task :models do
109
+ sh "railroad -i -l -a -m -M | dot -Tsvg | sed 's/font-size:14.00/font-size:11.00/g' > doc/models.svg"
110
+ end
111
+
112
+ task :controllers do
113
+ sh "railroad -i -l -C | neato -Tsvg | sed 's/font-size:14.00/font-size:11.00/g' > doc/controllers.svg"
114
+ end
115
+ end
116
+
117
+ task :diagrams => %w(diagram:models diagram:controllers)
118
+ end
119
+
120
+ Then, 'rake doc:diagrams' produces 'doc/models.svg' and 'doc/controllers.svg'.
121
+
122
+ = Requirements
123
+
124
+ RailRoad has been tested with Ruby 1.8.5 and Rails 1.1.6 to 1.2.3
125
+ applications. There is no additional requirements (nevertheless, all your
126
+ Rails application requirements must be installed).
127
+
128
+ In order to view/export the DOT diagrams, you'll need the processing tools
129
+ from Graphviz.
130
+
131
+ = Website and Project Home
132
+
133
+ http://railroad.rubyforge.org
134
+
135
+ = License
136
+
137
+ RailRoad is distributed under the terms of the GNU General Public License
138
+ as published by the Free Software Foundation; either version 2 of the
139
+ License, or (at your option) any later version.
140
+
141
+ = Author
142
+
143
+ Javier Smaldone
144
+ (javier -at- smaldone -dot- com -dot- ar, http://blog.smaldone.com.ar )
145
+
@@ -0,0 +1,15 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/railroad.rb'
6
+
7
+ Hoe.new('railroad', APP_VERSION.join('.')) do |p|
8
+ p.rubyforge_name = 'railroad'
9
+ p.author = "Javier Smaldone"
10
+ p.email = "javier@smaldone.com.ar"
11
+ p.url = "http://railroad.rubyforge.org"
12
+ p.summary = "A DOT diagram generator for Ruby on Rail applications"
13
+ end
14
+
15
+ # vim: syntax=Ruby
@@ -0,0 +1,45 @@
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
+ $: << File.join(File.dirname(__FILE__), '../lib/')
18
+ require 'railroad'
19
+
20
+ options = OptionsStruct.new
21
+
22
+ options.parse ARGV
23
+
24
+ old_dir = Dir.pwd
25
+
26
+ Dir.chdir(options.root) if options.root != ''
27
+
28
+ if options.command == 'models'
29
+ diagram = ModelsDiagram.new options
30
+ elsif options.command == 'controllers'
31
+ diagram = ControllersDiagram.new options
32
+ elsif options.command == 'aasm'
33
+ diagram = AasmDiagram.new options
34
+ else
35
+ STDERR.print "Error: You must supply a command\n" +
36
+ " (try #{APP_NAME} -h)\n\n"
37
+ exit 1
38
+ end
39
+
40
+ diagram.generate
41
+
42
+ Dir.chdir(old_dir)
43
+
44
+ diagram.print
45
+
data/init.rb ADDED
File without changes
@@ -0,0 +1,11 @@
1
+ APP_NAME = "railroad"
2
+ APP_HUMAN_NAME = "RailRoad"
3
+ APP_VERSION = [0,6,0]
4
+ COPYRIGHT = "Copyright (C) 2007-2008 Javier Smaldone"
5
+
6
+ require 'railroad/options_struct'
7
+ require 'railroad/diagram_graph'
8
+ require 'railroad/app_diagram'
9
+ require 'railroad/models_diagram'
10
+ require 'railroad/controllers_diagram'
11
+ require 'railroad/aasm_diagram'
@@ -0,0 +1,79 @@
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
+ # Diagram for Acts As State Machine
10
+ class AasmDiagram < AppDiagram
11
+
12
+ def initialize(options)
13
+ #options.exclude.map! {|e| e = "app/models/" + e}
14
+ super options
15
+ @graph.diagram_type = 'Models'
16
+ # Processed habtm associations
17
+ @habtm = []
18
+ end
19
+
20
+ # Process model files
21
+ def generate
22
+ STDERR.print "Generating AASM diagram\n" if @options.verbose
23
+ files = Dir.glob("app/models/*.rb")
24
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
25
+ files -= @options.exclude
26
+ files.each do |f|
27
+ process_class extract_class_name('app/models/', f).constantize
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Load model classes
34
+ def load_classes
35
+ begin
36
+ disable_stdout
37
+ files = Dir.glob("app/models/**/*.rb")
38
+ files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
39
+ files -= @options.exclude
40
+ files.each {|m| require m }
41
+ enable_stdout
42
+ rescue LoadError
43
+ enable_stdout
44
+ print_error "model classes"
45
+ raise
46
+ end
47
+ end # load_classes
48
+
49
+ # Process a model class
50
+ def process_class(current_class)
51
+
52
+ STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
53
+
54
+ # Only interested in acts_as_state_machine models.
55
+ return unless current_class.respond_to?'states'
56
+
57
+ node_attribs = []
58
+ node_type = 'aasm'
59
+
60
+ current_class.states.each do |state_name|
61
+ state = current_class.read_inheritable_attribute(:states)[state_name]
62
+ node_shape = (current_class.initial_state === state_name) ? ", peripheries = 2" : ""
63
+ node_attribs << "#{current_class.name.downcase}_#{state_name} [label=#{state_name} #{node_shape}];"
64
+ end
65
+ @graph.add_node [node_type, current_class.name, node_attribs]
66
+
67
+ current_class.read_inheritable_attribute(:transition_table).each do |event_name, event|
68
+ event.each do |transition|
69
+ @graph.add_edge [
70
+ 'event',
71
+ current_class.name.downcase + "_" + transition.from.to_s,
72
+ current_class.name.downcase + "_" + transition.to.to_s,
73
+ event_name.to_s
74
+ ]
75
+ end
76
+ end
77
+ end # process_class
78
+
79
+ end # class AasmDiagram
@@ -0,0 +1,86 @@
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
+ # Root class for RailRoad diagrams
8
+ class AppDiagram
9
+
10
+ def initialize(options)
11
+ @options = options
12
+ @graph = DiagramGraph.new
13
+ @graph.show_label = @options.label
14
+
15
+ STDERR.print "Loading application environment\n" if @options.verbose
16
+ load_environment
17
+
18
+ STDERR.print "Loading application classes\n" if @options.verbose
19
+ load_classes
20
+ end
21
+
22
+ # Print diagram
23
+ def print
24
+ if @options.output
25
+ old_stdout = STDOUT.dup
26
+ begin
27
+ STDOUT.reopen(@options.output)
28
+ rescue
29
+ STDERR.print "Error: Cannot write diagram to #{@options.output}\n\n"
30
+ exit 2
31
+ end
32
+ end
33
+
34
+ if @options.xmi
35
+ STDERR.print "Generating XMI diagram\n" if @options.verbose
36
+ STDOUT.print @graph.to_xmi
37
+ else
38
+ STDERR.print "Generating DOT graph\n" if @options.verbose
39
+ STDOUT.print @graph.to_dot
40
+ end
41
+
42
+ if @options.output
43
+ STDOUT.reopen(old_stdout)
44
+ end
45
+ end # print
46
+
47
+ private
48
+
49
+ # Prevents Rails application from writing to STDOUT
50
+ def disable_stdout
51
+ @old_stdout = STDOUT.dup
52
+ STDOUT.reopen(PLATFORM =~ /mswin/ ? "NUL" : "/dev/null")
53
+ end
54
+
55
+ # Restore STDOUT
56
+ def enable_stdout
57
+ STDOUT.reopen(@old_stdout)
58
+ end
59
+
60
+
61
+ # Print error when loading Rails application
62
+ def print_error(type)
63
+ STDERR.print "Error loading #{type}.\n (Are you running " +
64
+ "#{APP_NAME} on the aplication's root directory?)\n\n"
65
+ end
66
+
67
+ # Load Rails application's environment
68
+ def load_environment
69
+ begin
70
+ disable_stdout
71
+ require "config/environment"
72
+ enable_stdout
73
+ rescue LoadError
74
+ enable_stdout
75
+ print_error "application environment"
76
+ raise
77
+ end
78
+ end
79
+
80
+ # Extract class name from filename
81
+ def extract_class_name(base, filename)
82
+ # this is will handle directory names as namespace names
83
+ filename.reverse.chomp(base.reverse).reverse.chomp(".rb").camelize
84
+ end
85
+
86
+ end # class AppDiagram
@@ -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
+ # RailRoad controllers diagram
8
+ class ControllersDiagram < AppDiagram
9
+
10
+ def initialize(options)
11
+ #options.exclude.map! {|e| "app/controllers/" + e}
12
+ super options
13
+ @graph.diagram_type = 'Controllers'
14
+ end
15
+
16
+ # Process controller files
17
+ def generate
18
+ STDERR.print "Generating controllers diagram\n" if @options.verbose
19
+
20
+ files = Dir.glob("app/controllers/**/*_controller.rb") - @options.exclude
21
+ files << 'app/controllers/application.rb'
22
+ files.each do |f|
23
+ class_name = extract_class_name('app/controllers/', f)
24
+ # ApplicationController's file is 'application.rb'
25
+ class_name += 'Controller' if class_name == 'Application'
26
+ process_class class_name.constantize
27
+ end
28
+ end # generate
29
+
30
+ private
31
+
32
+ # Load controller classes
33
+ def load_classes
34
+ begin
35
+ disable_stdout
36
+ # ApplicationController must be loaded first
37
+ require "app/controllers/application.rb"
38
+ files = Dir.glob("app/controllers/**/*_controller.rb") - @options.exclude
39
+ files.each {|c| require c }
40
+ enable_stdout
41
+ rescue LoadError
42
+ enable_stdout
43
+ print_error "controller classes"
44
+ raise
45
+ end
46
+ end # load_classes
47
+
48
+ # Proccess a controller class
49
+ def process_class(current_class)
50
+
51
+ STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
52
+
53
+ if @options.brief
54
+ @graph.add_node ['controller-brief', current_class.name]
55
+ elsif current_class.is_a? Class
56
+ # Collect controller's methods
57
+ node_attribs = {:public => [],
58
+ :protected => [],
59
+ :private => []}
60
+ current_class.public_instance_methods(false).sort.each { |m|
61
+ node_attribs[:public] << m
62
+ } unless @options.hide_public
63
+ current_class.protected_instance_methods(false).sort.each { |m|
64
+ node_attribs[:protected] << m
65
+ } unless @options.hide_protected
66
+ current_class.private_instance_methods(false).sort.each { |m|
67
+ node_attribs[:private] << m
68
+ } unless @options.hide_private
69
+ @graph.add_node ['controller', current_class.name, node_attribs]
70
+ elsif @options.modules && current_class.is_a?(Module)
71
+ @graph.add_node ['module', current_class.name]
72
+ end
73
+
74
+ # Generate the inheritance edge (only for ApplicationControllers)
75
+ if @options.inheritance &&
76
+ (ApplicationController.subclasses.include? current_class.name)
77
+ @graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
78
+ end
79
+ end # process_class
80
+
81
+ end # class ControllersDiagram