railroad 0.2.0 → 0.3.0
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/README +28 -30
- data/lib/railroad +374 -182
- data/rake.gemspec +1 -1
- metadata +2 -2
data/README
CHANGED
@@ -11,47 +11,45 @@ output to a .dot file or pipe it to the dot or neato utilities to produce a
|
|
11
11
|
graphic. Model diagrams are intended to be processed using dot and
|
12
12
|
controller diagrams are best processed using neato.
|
13
13
|
|
14
|
-
railroad [options]
|
14
|
+
railroad [options] command
|
15
15
|
|
16
16
|
== Options
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
-
|
22
|
-
|
23
|
-
|
24
|
-
-
|
25
|
-
|
26
|
-
|
27
|
-
-
|
28
|
-
|
29
|
-
|
30
|
-
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
-
|
40
|
-
|
18
|
+
Common options:
|
19
|
+
-b, --brief Generate compact diagram
|
20
|
+
(no attributes nor methods)
|
21
|
+
-i, --inheritance Include inheritance relations
|
22
|
+
-l, --label Add a label with diagram information
|
23
|
+
(type, date, migration, version)
|
24
|
+
-o, --output FILE Write diagram to file FILE
|
25
|
+
|
26
|
+
Models diagram options:
|
27
|
+
-a, --all Include all models
|
28
|
+
(not only ActiveRecord::Base derived)
|
29
|
+
--hide-types Hide attributes type
|
30
|
+
-j, --join Concentrate edges
|
31
|
+
-m, --modules Include modules
|
32
|
+
|
33
|
+
Controllers diagram options:
|
34
|
+
--hide-public Hide public methods
|
35
|
+
--hide-protected Hide protected methods
|
36
|
+
--hide-private Hide private methods
|
37
|
+
|
38
|
+
Other options:
|
39
|
+
-h, --help Show this message
|
40
|
+
--version Show version and copyright
|
41
41
|
|
42
42
|
== Commands
|
43
43
|
|
44
|
-
-M
|
45
|
-
Generate
|
44
|
+
-M, --models Generate models diagram
|
45
|
+
-C, --controllers Generate controllers diagram
|
46
46
|
|
47
|
-
-C
|
48
|
-
Generate controllers diagram
|
49
47
|
|
50
48
|
== Examples
|
51
49
|
|
52
|
-
railroad -
|
50
|
+
railroad -o models.dot -M
|
53
51
|
Produces a models diagram to the file 'models.dot'
|
54
|
-
railroad -a -i -
|
52
|
+
railroad -a -i -o full_models.dot -M
|
55
53
|
Models diagram with all classes showing inheritance relations
|
56
54
|
railroad -M | dot -Tsvg > models.svg
|
57
55
|
Model diagram in SVG format
|
data/lib/railroad
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# RailRoad - RoR diagrams generator
|
4
|
-
# http://railroad.rubyforge.org
|
4
|
+
# http://railroad.rubyforge.org
|
5
|
+
#
|
6
|
+
# RailRoad generates models and controllers diagrams in DOT language
|
7
|
+
# for a Rails application.
|
5
8
|
#
|
6
9
|
# Copyright 2007 - Javier Smaldone (http://www.smaldone.com.ar)
|
7
10
|
#
|
@@ -10,232 +13,421 @@
|
|
10
13
|
# the Free Software Foundation; either version 2 of the License, or
|
11
14
|
# (at your option) any later version.
|
12
15
|
#
|
13
|
-
# Purpose:
|
14
|
-
# RailRoad generates models and controllers diagrams in DOT language
|
15
|
-
# for a Rails application.
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
17
|
+
APP_NAME = "railroad"
|
18
|
+
APP_HUMAN_NAME = "RailRoad"
|
19
|
+
APP_VERSION = [0,3,0]
|
20
|
+
COPYRIGHT = "Copyright (C) 2007 Javier Smaldone"
|
21
|
+
|
22
|
+
|
23
|
+
class OptionsParser
|
24
|
+
|
25
|
+
require 'optparse'
|
26
|
+
require 'ostruct'
|
27
|
+
|
28
|
+
def self.parse(args)
|
29
|
+
|
30
|
+
options = OpenStruct.new
|
31
|
+
|
32
|
+
options.all = false
|
33
|
+
options.brief = false
|
34
|
+
options.inheritance = false
|
35
|
+
options.join = false
|
36
|
+
options.label = false
|
37
|
+
options.modules = false
|
38
|
+
options.hide_types = false
|
39
|
+
options.hide_public = false
|
40
|
+
options.hide_protected = false
|
41
|
+
options.hide_private = false
|
42
|
+
options.command = ''
|
43
|
+
|
44
|
+
opts = OptionParser.new do |opts|
|
45
|
+
opts.banner = "Usage: #{APP_NAME} [options] command"
|
46
|
+
opts.separator ""
|
47
|
+
opts.separator "Common options:"
|
48
|
+
opts.on("-b", "--brief", "Generate compact diagram",
|
49
|
+
" (no attributes nor methods)") do |b|
|
50
|
+
options.brief = b
|
51
|
+
end
|
52
|
+
opts.on("-i", "--inheritance", "Include inheritance relations") do |i|
|
53
|
+
options.inheritance = i
|
54
|
+
end
|
55
|
+
opts.on("-l", "--label", "Add a label with diagram information",
|
56
|
+
" (type, date, migration, version)") do |l|
|
57
|
+
options.label = l
|
58
|
+
end
|
59
|
+
opts.on("-o", "--output FILE", "Write diagram to file FILE") do |f|
|
60
|
+
options.output = f
|
61
|
+
end
|
62
|
+
opts.separator ""
|
63
|
+
opts.separator "Models diagram options:"
|
64
|
+
opts.on("-a", "--all", "Include all models",
|
65
|
+
" (not only ActiveRecord::Base derived)") do |a|
|
66
|
+
options.all = a
|
67
|
+
end
|
68
|
+
opts.on("--hide-types", "Hide attributes type") do |h|
|
69
|
+
options.hide_types = h
|
70
|
+
end
|
71
|
+
opts.on("-j", "--join", "Concentrate edges") do |j|
|
72
|
+
options.join = j
|
73
|
+
end
|
74
|
+
opts.on("-m", "--modules", "Include modules") do |m|
|
75
|
+
options.modules = m
|
76
|
+
end
|
77
|
+
opts.separator ""
|
78
|
+
opts.separator "Controllers diagram options:"
|
79
|
+
opts.on("--hide-public", "Hide public methods") do |h|
|
80
|
+
options.hide_public = h
|
81
|
+
end
|
82
|
+
opts.on("--hide-protected", "Hide protected methods") do |h|
|
83
|
+
options.hide_protected = h
|
84
|
+
end
|
85
|
+
opts.on("--hide-private", "Hide private methods") do |h|
|
86
|
+
options.hide_private = h
|
87
|
+
end
|
88
|
+
opts.separator ""
|
89
|
+
opts.separator "Other options:"
|
90
|
+
opts.on("-h", "--help", "Show this message") do
|
91
|
+
print "#{opts}\n"
|
92
|
+
exit
|
93
|
+
end
|
94
|
+
opts.on("--version", "Show version and copyright") do
|
95
|
+
print "#{APP_HUMAN_NAME} version #{APP_VERSION.join('.')}\n\n" +
|
96
|
+
"#{COPYRIGHT}\n" +
|
97
|
+
"This is free software; see the source for copying conditions.\n\n"
|
98
|
+
exit
|
99
|
+
end
|
100
|
+
opts.separator ""
|
101
|
+
opts.separator "Commands (you must supply one of these):"
|
102
|
+
opts.on("-M", "--models", "Generate models diagram") do |c|
|
103
|
+
if options.command == 'controllers'
|
104
|
+
$stderr.print "Error: Can't generate models AND controllers diagram\n\n"
|
105
|
+
exit 1
|
106
|
+
else
|
107
|
+
options.command = 'models'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
opts.on("-C", "--controllers", "Generate controllers diagram") do |c|
|
111
|
+
if options.command == 'models'
|
112
|
+
$stderr.print "Error: Can't generate models AND controllers diagram\n\n"
|
113
|
+
exit 1
|
114
|
+
else
|
115
|
+
options.command = 'controllers'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
opts.separator ""
|
119
|
+
opts.separator "For bug reporting instructions and additional information, please see:"
|
120
|
+
opts.separator "http://railroad.rubyforge.org"
|
121
|
+
end
|
122
|
+
|
123
|
+
begin
|
124
|
+
opts.parse!(args)
|
125
|
+
rescue OptionParser::AmbiguousOption
|
126
|
+
option_error "Ambiguous option", opts
|
127
|
+
rescue OptionParser::InvalidOption
|
128
|
+
option_error "Invalid option", opts
|
129
|
+
rescue OptionParser::InvalidArgument
|
130
|
+
option_error "Invalid argument", opts
|
131
|
+
rescue OptionParser::MissingArgument
|
132
|
+
option_error "Missing argument", opts
|
133
|
+
rescue
|
134
|
+
option_error "Unknown error", opts
|
135
|
+
end
|
136
|
+
options
|
137
|
+
end # self.parse
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def self.option_error(msg, opts)
|
142
|
+
$stderr.print "Error: #{msg}\n\n #{opts}\n"
|
143
|
+
exit 1
|
144
|
+
end
|
145
|
+
|
146
|
+
end # class OptionsParser
|
147
|
+
|
37
148
|
|
38
|
-
|
149
|
+
class AppDiagram
|
150
|
+
|
151
|
+
def initialize(options)
|
152
|
+
@options = options
|
153
|
+
load_environment
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
# Quotes a class name
|
159
|
+
def node(name)
|
39
160
|
'"' + name + '"'
|
40
|
-
end
|
161
|
+
end
|
41
162
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
163
|
+
# Print diagram label
|
164
|
+
def print_info(type)
|
165
|
+
print "\t_diagram_info [shape=\"plaintext\", label=\"Diagram: #{type}\\l" +
|
166
|
+
"Date: #{Time.now.strftime "%b %d %Y - %H:%M"}\\l" +
|
167
|
+
"Migration version: #{ActiveRecord::Migrator.current_version}\\l" +
|
168
|
+
"Generated by #{APP_HUMAN_NAME} #{APP_VERSION.join('.')}\\l\""+
|
169
|
+
", fontsize=14]\n"
|
170
|
+
end
|
49
171
|
|
50
|
-
def print_error(type)
|
51
|
-
STDERR.print "Error loading #{type}
|
52
|
-
|
53
|
-
end
|
172
|
+
def print_error(type)
|
173
|
+
STDERR.print "Error loading #{type}.\n (Are you running " +
|
174
|
+
"#{APP_NAME} on the aplication's root directory?)\n\n"
|
175
|
+
end
|
54
176
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
177
|
+
# Load Rails application's environment
|
178
|
+
def load_environment
|
179
|
+
begin
|
180
|
+
require "config/environment"
|
181
|
+
rescue LoadError
|
182
|
+
print_error "app environment"
|
183
|
+
raise
|
184
|
+
end
|
62
185
|
end
|
63
186
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
187
|
+
end # class AppDiagram
|
188
|
+
|
189
|
+
|
190
|
+
class ModelsDiagram < AppDiagram
|
191
|
+
|
192
|
+
# Generate models diagram
|
193
|
+
def generate
|
194
|
+
|
195
|
+
load_classes
|
196
|
+
|
197
|
+
# DOT diagram header
|
198
|
+
print "digraph models_diagram {\n"
|
199
|
+
print "\tgraph[concentrate=true]\n" if @options.join
|
200
|
+
print_info "Models" if @options.label
|
201
|
+
|
202
|
+
# Processed habtm associations
|
203
|
+
@habtm = []
|
204
|
+
|
205
|
+
models_files = Dir.glob("app/models/**/*.rb")
|
206
|
+
models_files.each do |m|
|
207
|
+
# Extract the class name from the file name
|
208
|
+
current_class = m.split('/')[2..-1].join('/').split('.').first.camelize.constantize
|
209
|
+
process_class current_class
|
210
|
+
end
|
211
|
+
print "}\n"
|
68
212
|
|
69
|
-
models_files = Dir.glob("app/models/**/*.rb")
|
70
|
-
models_files.each do |m|
|
71
|
-
# Extract the class name from the file name
|
72
|
-
current_class = m.split('/')[2..-1].join('/').split('.').first.camelize.constantize
|
73
213
|
|
214
|
+
end # generate
|
215
|
+
|
216
|
+
private
|
217
|
+
|
218
|
+
# Load model classes
|
219
|
+
def load_classes
|
220
|
+
begin
|
221
|
+
Dir.glob("app/models/**/*.rb") {|m| require m }
|
222
|
+
rescue LoadError
|
223
|
+
print_error "model classes"
|
224
|
+
raise
|
225
|
+
end
|
226
|
+
end # load_classes
|
227
|
+
|
228
|
+
# Process model class
|
229
|
+
def process_class(current_class)
|
230
|
+
|
231
|
+
printed = false
|
232
|
+
|
74
233
|
# Is current_clas derived from ActiveRecord::Base?
|
75
234
|
if current_class.respond_to?'reflect_on_all_associations'
|
76
235
|
|
77
236
|
# Print the node
|
78
|
-
if @brief
|
237
|
+
if @options.brief
|
79
238
|
print "\t#{node(current_class.name)}\n"
|
80
239
|
else
|
81
|
-
print "\t#{node(current_class.name)} "
|
82
|
-
|
240
|
+
print "\t#{node(current_class.name)} " +
|
241
|
+
"[shape=Mrecord, label=\"{#{current_class.name}|"
|
83
242
|
current_class.content_columns.each do |a|
|
84
|
-
print "#{a.name}
|
243
|
+
print "#{a.name}"
|
244
|
+
print " :#{a.type.to_s}" unless @options.hide_types
|
245
|
+
print "\\l"
|
85
246
|
end
|
86
247
|
print "}\"]\n"
|
87
248
|
end
|
88
|
-
|
249
|
+
printed = true
|
89
250
|
# Iterate over the class associations
|
90
|
-
current_class.reflect_on_all_associations.each
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
params = "label=\"#{association.name.to_s}\", "
|
95
|
-
else
|
96
|
-
params = ""
|
97
|
-
end
|
98
|
-
|
99
|
-
# Skip "belongs_to" associations
|
100
|
-
if association.macro.to_s != 'belongs_to'
|
101
|
-
# Put a tail label with the association arity
|
102
|
-
if association.macro.to_s == 'has_one'
|
103
|
-
params += 'taillabel="1"'
|
104
|
-
else
|
105
|
-
params += 'taillabel="n"'
|
106
|
-
end
|
107
|
-
|
108
|
-
# Print the edge
|
109
|
-
print "\t\t#{node(current_class.name)} -> "
|
110
|
-
print "#{node(association.class_name)} "
|
111
|
-
print "[ #{params} ]\n"
|
112
|
-
end
|
113
|
-
end # Associations
|
114
|
-
|
115
|
-
if @inherit && (current_class.superclass != ActiveRecord::Base)
|
116
|
-
# Print the inheritance edge
|
117
|
-
print "\t\t#{node(current_class.name)} -> "
|
118
|
-
print "#{node(current_class.superclass.name)}"
|
119
|
-
print " [arrowhead=\"onormal\"]\n"
|
120
|
-
end
|
121
|
-
|
122
|
-
elsif @all_classes
|
251
|
+
current_class.reflect_on_all_associations.each { |a|
|
252
|
+
process_association(current_class, a)
|
253
|
+
}
|
254
|
+
elsif @options.all && (current_class.is_a? Class)
|
123
255
|
# Not ActiveRecord::Base model
|
124
|
-
if @brief
|
256
|
+
if @options.brief
|
125
257
|
print "\t#{node(current_class.name)} [shape=box]\n"
|
126
258
|
else
|
127
|
-
print "\t#{node(current_class.name)}"
|
128
|
-
|
259
|
+
print "\t#{node(current_class.name)}" +
|
260
|
+
"[shape=record, label=\"{#{current_class.name}|}\"]\n"
|
129
261
|
end
|
262
|
+
printed = true
|
263
|
+
elsif @options.modules && (current_class.is_a? Module)
|
264
|
+
print "\t#{node(current_class.name)}" +
|
265
|
+
"[shape=box, style=dotted, label=\"#{current_class.name}\"]\n"
|
130
266
|
end
|
131
|
-
end # Dir
|
132
|
-
print "}\n"
|
133
|
-
end # generate_models
|
134
267
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
268
|
+
# Only consider meaningful inheritance relations for printed classes
|
269
|
+
if @options.inheritance && printed &&
|
270
|
+
(current_class.superclass != ActiveRecord::Base) &&
|
271
|
+
(current_class.superclass != Object)
|
272
|
+
print "\t\t#{node(current_class.name)} -> " +
|
273
|
+
"#{node(current_class.superclass.name)}" +
|
274
|
+
" [arrowhead=\"onormal\"]\n"
|
275
|
+
end
|
276
|
+
|
277
|
+
end # process_class
|
278
|
+
|
279
|
+
# Process model association
|
280
|
+
def process_association(current_class, association)
|
281
|
+
|
282
|
+
# Only non standard association names needs a label
|
283
|
+
if association.class_name != association.name.to_s.singularize.camelize
|
284
|
+
params = "label=\"#{association.name.to_s}\", "
|
285
|
+
else
|
286
|
+
params = ""
|
142
287
|
end
|
143
|
-
rescue LoadError
|
144
|
-
print_error "controller classes"
|
145
|
-
raise
|
146
|
-
end
|
147
288
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
289
|
+
# Skip "belongs_to" associations
|
290
|
+
if association.macro.to_s != 'belongs_to'
|
291
|
+
# Put a tail label with the association arity
|
292
|
+
if association.macro.to_s == 'has_one'
|
293
|
+
params += 'taillabel="1"'
|
294
|
+
else
|
295
|
+
params += 'taillabel="n"'
|
296
|
+
end
|
297
|
+
|
298
|
+
# Use double-headed arrows for habtm and has_many, :through
|
299
|
+
if association.macro.to_s == 'has_and_belongs_to_many' ||
|
300
|
+
(association.macro.to_s == 'has_many' && association.options[:through])
|
301
|
+
if @habtm.include? "#{association.class_name} -> #{current_class.name}"
|
302
|
+
# habtm association already considered
|
303
|
+
return
|
304
|
+
else
|
305
|
+
params += ', headlabel="n", arrowtail="normal"'
|
306
|
+
@habtm << "#{current_class.name} -> #{association.class_name}"
|
307
|
+
end
|
308
|
+
end
|
309
|
+
# Print the edge
|
310
|
+
print "\t\t#{node(current_class.name)} -> " +
|
311
|
+
"#{node(association.class_name)} " +
|
312
|
+
"[ #{params} ]\n"
|
313
|
+
end
|
314
|
+
end # process_association
|
315
|
+
|
316
|
+
end # class ModelsDiagram
|
317
|
+
|
318
|
+
|
319
|
+
class ControllersDiagram < AppDiagram
|
152
320
|
|
153
|
-
|
321
|
+
# Generate controllers diagram
|
322
|
+
def generate
|
154
323
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
324
|
+
load_classes
|
325
|
+
|
326
|
+
# DOT diagram header
|
327
|
+
print "digraph controllers_diagram {\n" +
|
328
|
+
"\tgraph[overlap=false, splines=true]\n"
|
329
|
+
print_info "Controllers" if @options.label
|
330
|
+
|
331
|
+
@app_controller = ApplicationController
|
332
|
+
|
333
|
+
controllers_files = Dir.glob("app/controllers/**/*_controller.rb")
|
334
|
+
controllers_files << 'app/controllers/application.rb'
|
335
|
+
controllers_files.each do |c|
|
336
|
+
|
337
|
+
# Extract the class name from the file name
|
338
|
+
class_name = c.split('/')[2..-1].join('/').split('.').first.camelize
|
339
|
+
|
340
|
+
# ApplicationController's file is 'application.rb'
|
341
|
+
if class_name == 'Application'
|
342
|
+
class_name = 'ApplicationController'
|
343
|
+
end
|
344
|
+
|
345
|
+
process_class class_name.constantize
|
160
346
|
|
161
|
-
# ApplicationController's file is 'application.rb'
|
162
|
-
if class_name == 'Application'
|
163
|
-
class_name = 'ApplicationController'
|
164
347
|
end
|
165
|
-
|
348
|
+
print "}\n"
|
349
|
+
end # generate
|
350
|
+
|
351
|
+
private
|
166
352
|
|
353
|
+
# Load controller classes
|
354
|
+
def load_classes
|
355
|
+
begin
|
356
|
+
# ApplicationController must be loaded first
|
357
|
+
require "app/controllers/application.rb"
|
358
|
+
Dir.glob("app/controllers/**/*_controller.rb") do |c|
|
359
|
+
require c
|
360
|
+
end
|
361
|
+
rescue LoadError
|
362
|
+
print_error "controller classes"
|
363
|
+
raise
|
364
|
+
end
|
365
|
+
end # load_classes
|
366
|
+
|
367
|
+
# Proccess controller class
|
368
|
+
def process_class(current_class)
|
167
369
|
# Print the node
|
168
|
-
if @brief
|
370
|
+
if @options.brief
|
169
371
|
print "\t#{node(current_class.name)}\n"
|
170
|
-
|
171
|
-
print "\t#{node(current_class.name)} "
|
172
|
-
|
173
|
-
current_class.public_instance_methods(false).sort.each
|
372
|
+
elsif current_class.is_a? Class
|
373
|
+
print "\t#{node(current_class.name)} " +
|
374
|
+
"[shape=Mrecord, label=\"{#{current_class.name}|"
|
375
|
+
current_class.public_instance_methods(false).sort.each { |m|
|
174
376
|
print "#{m}\\l"
|
175
|
-
|
176
|
-
print "|"
|
177
|
-
current_class.protected_instance_methods(false).sort.each
|
377
|
+
} unless @options.hide_public
|
378
|
+
print "|"
|
379
|
+
current_class.protected_instance_methods(false).sort.each { |m|
|
178
380
|
print "#{m}\\l"
|
179
|
-
|
180
|
-
print "|"
|
181
|
-
current_class.private_instance_methods(false).sort.each
|
381
|
+
} unless @options.hide_protected
|
382
|
+
print "|"
|
383
|
+
current_class.private_instance_methods(false).sort.each { |m|
|
182
384
|
print "#{m}\\l"
|
183
|
-
|
184
|
-
print "}\"]\n"
|
385
|
+
} unless @options.hide_private
|
386
|
+
print "}\"]\n"
|
387
|
+
elsif @options.modules && (current_class.is_a? Module)
|
388
|
+
print "\t#{node(current_class.name)}" +
|
389
|
+
"[shape=box, style=dotted, label=\"#{current_class.name}\"]\n"
|
185
390
|
end
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
print "
|
391
|
+
|
392
|
+
# Print the inheritance edge
|
393
|
+
if @options.inheritance &&
|
394
|
+
(@app_controller.subclasses.include? current_class.name)
|
395
|
+
print "\t#{node(current_class.name)} -> " +
|
396
|
+
"#{node(current_class.superclass.name)} " +
|
397
|
+
"[arrowhead=\"onormal\"]\n"
|
191
398
|
end
|
192
|
-
end # Dir
|
193
|
-
print "}\n"
|
194
|
-
end # generate_controllers
|
195
|
-
|
196
|
-
# Main program
|
197
|
-
if ARGV.include?('--help') || ARGV.include?('-h')
|
198
|
-
print_help
|
199
|
-
exit
|
200
|
-
elsif ARGV.include?('--version') || ARGV.include?('-v')
|
201
|
-
print "#{@app_name} #{@version}\n#{@copyright}\n\n"
|
202
|
-
exit
|
203
|
-
end
|
204
399
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
STDERR.print "(try '#{@app_name} --help')\n\n"
|
222
|
-
exit 1
|
223
|
-
elsif ! (ARGV.include?('-M') || ARGV.include?('-C'))
|
224
|
-
STDERR.print "Error: you must specify a command\n"
|
225
|
-
STDERR.print "(try '#{@app_name} --help')\n\n"
|
400
|
+
end # process_class
|
401
|
+
|
402
|
+
end # class ControllersDiagram
|
403
|
+
|
404
|
+
|
405
|
+
# Main program
|
406
|
+
|
407
|
+
options = OptionsParser.parse ARGV
|
408
|
+
|
409
|
+
if options.command == 'models'
|
410
|
+
diagram = ModelsDiagram.new options
|
411
|
+
elsif options.command == 'controllers'
|
412
|
+
diagram = ControllersDiagram.new options
|
413
|
+
else
|
414
|
+
$stderr.print "Error: You must supply a command\n" +
|
415
|
+
" (try #{APP_NAME} -h)\n\n"
|
226
416
|
exit 1
|
227
417
|
end
|
228
418
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
419
|
+
if options.output
|
420
|
+
old_stdout = $stdout
|
421
|
+
begin
|
422
|
+
$stdout = File.open(options.output, "w")
|
423
|
+
rescue
|
424
|
+
$stderr.print "Error: Cannot write to #{options.output}\n\n"
|
425
|
+
exit 2
|
426
|
+
end
|
235
427
|
end
|
236
428
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
429
|
+
diagram.generate
|
430
|
+
|
431
|
+
if options.out
|
432
|
+
$stdout = old_stdout
|
241
433
|
end
|
data/rake.gemspec
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: railroad
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-04-
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-04-09 00:00:00 -03:00
|
8
8
|
summary: A DOT diagram generator for Ruby on Rail applications
|
9
9
|
require_paths:
|
10
10
|
- lib
|