factorylabs-railroad 0.6.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.
@@ -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