tobias-railroad 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +7 -0
- data/AUTHORS.rdoc +16 -0
- data/CHANGELOG.rdoc +104 -0
- data/LICENSE.rdoc +340 -0
- data/README.rdoc +169 -0
- data/Rakefile +46 -0
- data/VERSION.yml +5 -0
- data/bin/railroad +53 -0
- data/lib/railroad.rb +2 -0
- data/lib/railroad/aasm_diagram.rb +109 -0
- data/lib/railroad/app_diagram.rb +112 -0
- data/lib/railroad/controllers_diagram.rb +95 -0
- data/lib/railroad/diagram_graph.rb +130 -0
- data/lib/railroad/models_diagram.rb +146 -0
- data/lib/railroad/options_struct.rb +178 -0
- data/lib/railroad/version.rb +14 -0
- data/spec/aasm_diagram_spec.rb +49 -0
- data/spec/app_diagram_spec.rb +15 -0
- data/spec/controllers_diagram_spec.rb +49 -0
- data/spec/diagram_graph_spec.rb +49 -0
- data/spec/file_fixture/app/controllers/application_controller.rb +2 -0
- data/spec/file_fixture/app/controllers/dummy1_controller.rb +0 -0
- data/spec/file_fixture/app/controllers/dummy2_controller.rb +0 -0
- data/spec/file_fixture/app/controllers/sub-dir/sub_dummy_controller.rb +0 -0
- data/spec/file_fixture/app/models/dummy1.rb +0 -0
- data/spec/file_fixture/app/models/dummy2.rb +0 -0
- data/spec/file_fixture/app/models/sub-dir/sub_dummy.rb +0 -0
- data/spec/models_diagram_spec.rb +49 -0
- data/spec/spec_helper.rb +9 -0
- metadata +116 -0
@@ -0,0 +1,95 @@
|
|
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
|
+
require 'railroad/app_diagram'
|
8
|
+
|
9
|
+
# RailRoad controllers diagram
|
10
|
+
class ControllersDiagram < AppDiagram
|
11
|
+
|
12
|
+
# as of Rails 2.3 the file is no longer application.rb but instead
|
13
|
+
# application_controller.rb
|
14
|
+
APP_CONTROLLER = File.exist?('app/controllers/application.rb') ? 'app/controllers/application.rb' : 'app/controllers/application_controller.rb'
|
15
|
+
|
16
|
+
def initialize(options = OptionsStruct.new)
|
17
|
+
#options.exclude.map! {|e| "app/controllers/" + e}
|
18
|
+
super options
|
19
|
+
@graph.diagram_type = 'Controllers'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Process controller files
|
23
|
+
def generate
|
24
|
+
STDERR.print "Generating controllers diagram\n" if @options.verbose
|
25
|
+
files = get_files
|
26
|
+
# only add APP_CONTROLLER if it isn't already included from the glob above
|
27
|
+
files << APP_CONTROLLER unless files.include? APP_CONTROLLER
|
28
|
+
files.each do |f|
|
29
|
+
class_name = extract_class_name(f)
|
30
|
+
# ApplicationController's file is 'application.rb' in Rails < 2.3
|
31
|
+
class_name += 'Controller' if class_name == 'Application'
|
32
|
+
begin
|
33
|
+
process_class class_name.constantize
|
34
|
+
rescue Exception
|
35
|
+
STDERR.print "Warning: exception #{$!} raised while trying to load controller class #{f}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end # generate
|
39
|
+
|
40
|
+
def get_files(prefix ='')
|
41
|
+
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix << "app/controllers/**/*_controller.rb")
|
42
|
+
files -= Dir.glob(@options.exclude)
|
43
|
+
files
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
# Load controller classes
|
48
|
+
def load_classes
|
49
|
+
begin
|
50
|
+
disable_stdout
|
51
|
+
# ApplicationController must be loaded first
|
52
|
+
require APP_CONTROLLER
|
53
|
+
get_files.each {|c| require "./#{c}" }
|
54
|
+
enable_stdout
|
55
|
+
rescue LoadError
|
56
|
+
enable_stdout
|
57
|
+
print_error "controller classes"
|
58
|
+
raise
|
59
|
+
end
|
60
|
+
end # load_classes
|
61
|
+
|
62
|
+
# Proccess a controller class
|
63
|
+
def process_class(current_class)
|
64
|
+
|
65
|
+
STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
|
66
|
+
|
67
|
+
if @options.brief
|
68
|
+
@graph.add_node ['controller-brief', current_class.name]
|
69
|
+
elsif current_class.is_a? Class
|
70
|
+
# Collect controller's methods
|
71
|
+
node_attribs = {:public => [],
|
72
|
+
:protected => [],
|
73
|
+
:private => []}
|
74
|
+
current_class.public_instance_methods(false).sort.each { |m|
|
75
|
+
node_attribs[:public] << m
|
76
|
+
} unless @options.hide_public
|
77
|
+
current_class.protected_instance_methods(false).sort.each { |m|
|
78
|
+
node_attribs[:protected] << m
|
79
|
+
} unless @options.hide_protected
|
80
|
+
current_class.private_instance_methods(false).sort.each { |m|
|
81
|
+
node_attribs[:private] << m
|
82
|
+
} unless @options.hide_private
|
83
|
+
@graph.add_node ['controller', current_class.name, node_attribs]
|
84
|
+
elsif @options.modules && current_class.is_a?(Module)
|
85
|
+
@graph.add_node ['module', current_class.name]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Generate the inheritance edge (only for ApplicationControllers)
|
89
|
+
if @options.inheritance &&
|
90
|
+
(ApplicationController.subclasses.include? current_class.name)
|
91
|
+
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
92
|
+
end
|
93
|
+
end # process_class
|
94
|
+
|
95
|
+
end # class ControllersDiagram
|
@@ -0,0 +1,130 @@
|
|
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
|
+
|
8
|
+
# RailRoad diagram structure
|
9
|
+
class DiagramGraph
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@diagram_type = ''
|
13
|
+
@show_label = false
|
14
|
+
@nodes = []
|
15
|
+
@edges = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_node(node)
|
19
|
+
@nodes << node
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_edge(edge)
|
23
|
+
@edges << edge
|
24
|
+
end
|
25
|
+
|
26
|
+
def diagram_type= (type)
|
27
|
+
@diagram_type = type
|
28
|
+
end
|
29
|
+
|
30
|
+
def show_label= (value)
|
31
|
+
@show_label = value
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# Generate DOT graph
|
36
|
+
def to_dot
|
37
|
+
return dot_header +
|
38
|
+
@nodes.map{|n| dot_node n[0], n[1], n[2]}.join +
|
39
|
+
@edges.map{|e| dot_edge e[0], e[1], e[2], e[3]}.join +
|
40
|
+
dot_footer
|
41
|
+
end
|
42
|
+
|
43
|
+
# Generate XMI diagram (not yet implemented)
|
44
|
+
def to_xmi
|
45
|
+
STDERR.print "Sorry. XMI output not yet implemented.\n\n"
|
46
|
+
return ""
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Build DOT diagram header
|
52
|
+
def dot_header
|
53
|
+
result = "digraph #{@diagram_type.downcase}_diagram {\n" +
|
54
|
+
"\tgraph[overlap=false, splines=true]\n"
|
55
|
+
result += dot_label if @show_label
|
56
|
+
return result
|
57
|
+
end
|
58
|
+
|
59
|
+
# Build DOT diagram footer
|
60
|
+
def dot_footer
|
61
|
+
return "}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Build diagram label
|
65
|
+
def dot_label
|
66
|
+
return "\t_diagram_info [shape=\"plaintext\", " +
|
67
|
+
"label=\"#{@diagram_type} diagram\\l" +
|
68
|
+
"Date: #{Time.now.strftime "%b %d %Y - %H:%M"}\\l" +
|
69
|
+
"Migration version: " +
|
70
|
+
"#{ActiveRecord::Migrator.current_version}\\l" +
|
71
|
+
"Generated by #{APP_HUMAN_NAME} #{APP_VERSION}"+
|
72
|
+
"\\l\", fontsize=14]\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Build a DOT graph node
|
76
|
+
def dot_node(type, name, attributes=nil)
|
77
|
+
case type
|
78
|
+
when 'model'
|
79
|
+
options = 'shape=Mrecord, label="{' + name + '|'
|
80
|
+
options += attributes.join('\l')
|
81
|
+
options += '\l}"'
|
82
|
+
when 'model-brief'
|
83
|
+
options = ''
|
84
|
+
when 'class'
|
85
|
+
options = 'shape=record, label="{' + name + '|}"'
|
86
|
+
when 'class-brief'
|
87
|
+
options = 'shape=box'
|
88
|
+
when 'controller'
|
89
|
+
options = 'shape=Mrecord, label="{' + name + '|'
|
90
|
+
public_methods = attributes[:public].join('\l')
|
91
|
+
protected_methods = attributes[:protected].join('\l')
|
92
|
+
private_methods = attributes[:private].join('\l')
|
93
|
+
options += public_methods + '\l|' + protected_methods + '\l|' +
|
94
|
+
private_methods + '\l'
|
95
|
+
options += '}"'
|
96
|
+
when 'controller-brief'
|
97
|
+
options = ''
|
98
|
+
when 'module'
|
99
|
+
options = 'shape=box, style=dotted, label="' + name + '"'
|
100
|
+
when 'aasm'
|
101
|
+
# Return subgraph format
|
102
|
+
return "subgraph cluster_#{name.downcase} {\n\tlabel = #{quote(name)}\n\t#{attributes.join("\n ")}}"
|
103
|
+
end # case
|
104
|
+
return "\t#{quote(name)} [#{options}]\n"
|
105
|
+
end # dot_node
|
106
|
+
|
107
|
+
# Build a DOT graph edge
|
108
|
+
def dot_edge(type, from, to, name = '')
|
109
|
+
options = name != '' ? "label=\"#{name}\", " : ''
|
110
|
+
case type
|
111
|
+
when 'one-one'
|
112
|
+
options += 'arrowtail=odot, arrowhead=dot, dir=both'
|
113
|
+
when 'one-many'
|
114
|
+
options += 'arrowtail=odot, arrowhead=crow, dir=both'
|
115
|
+
when 'many-many'
|
116
|
+
options += 'arrowtail=crow, arrowhead=crow, dir=both'
|
117
|
+
when 'is-a'
|
118
|
+
options += 'arrowhead="none", arrowtail="onormal"'
|
119
|
+
when 'event'
|
120
|
+
options += "fontsize=10"
|
121
|
+
end
|
122
|
+
return "\t#{quote(from)} -> #{quote(to)} [#{options}]\n"
|
123
|
+
end # dot_edge
|
124
|
+
|
125
|
+
# Quotes a class name
|
126
|
+
def quote(name)
|
127
|
+
'"' + name.to_s + '"'
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class DiagramGraph
|
@@ -0,0 +1,146 @@
|
|
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
|
+
require 'railroad/app_diagram'
|
8
|
+
|
9
|
+
# RailRoad models diagram
|
10
|
+
class ModelsDiagram < AppDiagram
|
11
|
+
|
12
|
+
def initialize(options = OptionsStruct.new)
|
13
|
+
#options.exclude.map! {|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 models diagram\n" if @options.verbose
|
23
|
+
get_files.each do |f|
|
24
|
+
begin
|
25
|
+
process_class extract_class_name(f).constantize
|
26
|
+
rescue Exception
|
27
|
+
STDERR.print "Warning: exception #{$!} raised while trying to load model class #{f}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_files(prefix ='')
|
34
|
+
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix << "app/models/**/*.rb")
|
35
|
+
files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
|
36
|
+
files -= Dir.glob(@options.exclude)
|
37
|
+
files
|
38
|
+
end
|
39
|
+
|
40
|
+
# Process a model class
|
41
|
+
def process_class(current_class)
|
42
|
+
|
43
|
+
STDERR.print "\tProcessing #{current_class}\n" if @options.verbose
|
44
|
+
|
45
|
+
generated = false
|
46
|
+
|
47
|
+
# Is current_clas derived from ActiveRecord::Base?
|
48
|
+
if current_class.respond_to?'reflect_on_all_associations'
|
49
|
+
|
50
|
+
|
51
|
+
node_attribs = []
|
52
|
+
if @options.brief || current_class.abstract_class?
|
53
|
+
node_type = 'model-brief'
|
54
|
+
else
|
55
|
+
node_type = 'model'
|
56
|
+
|
57
|
+
# Collect model's content columns
|
58
|
+
|
59
|
+
content_columns = current_class.content_columns
|
60
|
+
|
61
|
+
if @options.hide_magic
|
62
|
+
# From patch #13351
|
63
|
+
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
64
|
+
magic_fields = [
|
65
|
+
"created_at", "created_on", "updated_at", "updated_on",
|
66
|
+
"lock_version", "type", "id", "position", "parent_id", "lft",
|
67
|
+
"rgt", "quote", "template"
|
68
|
+
]
|
69
|
+
magic_fields << current_class.table_name + "_count" if current_class.respond_to? 'table_name'
|
70
|
+
content_columns = current_class.content_columns.select {|c| ! magic_fields.include? c.name}
|
71
|
+
else
|
72
|
+
content_columns = current_class.content_columns
|
73
|
+
end
|
74
|
+
|
75
|
+
content_columns.each do |a|
|
76
|
+
content_column = a.name
|
77
|
+
content_column += ' :' + a.type.to_s unless @options.hide_types
|
78
|
+
node_attribs << content_column
|
79
|
+
end
|
80
|
+
end
|
81
|
+
@graph.add_node [node_type, current_class.name, node_attribs]
|
82
|
+
generated = true
|
83
|
+
# Process class associations
|
84
|
+
associations = current_class.reflect_on_all_associations
|
85
|
+
if @options.inheritance && ! @options.transitive
|
86
|
+
superclass_associations = current_class.superclass.reflect_on_all_associations
|
87
|
+
|
88
|
+
associations = associations.select{|a| ! superclass_associations.include? a}
|
89
|
+
# This doesn't works!
|
90
|
+
# associations -= current_class.superclass.reflect_on_all_associations
|
91
|
+
end
|
92
|
+
associations.each do |a|
|
93
|
+
process_association current_class.name, a
|
94
|
+
end
|
95
|
+
elsif @options.all && (current_class.is_a? Class)
|
96
|
+
# Not ActiveRecord::Base model
|
97
|
+
node_type = @options.brief ? 'class-brief' : 'class'
|
98
|
+
@graph.add_node [node_type, current_class.name]
|
99
|
+
generated = true
|
100
|
+
elsif @options.modules && (current_class.is_a? Module)
|
101
|
+
@graph.add_node ['module', current_class.name]
|
102
|
+
end
|
103
|
+
|
104
|
+
# Only consider meaningful inheritance relations for generated classes
|
105
|
+
if @options.inheritance && generated &&
|
106
|
+
(current_class.superclass != ActiveRecord::Base) &&
|
107
|
+
(current_class.superclass != Object)
|
108
|
+
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
109
|
+
end
|
110
|
+
|
111
|
+
end # process_class
|
112
|
+
|
113
|
+
# Process a model association
|
114
|
+
def process_association(class_name, assoc)
|
115
|
+
|
116
|
+
STDERR.print "\t\tProcessing model association #{assoc.name.to_s}\n" if @options.verbose
|
117
|
+
|
118
|
+
# Skip "belongs_to" associations
|
119
|
+
return if assoc.macro.to_s == 'belongs_to' && !@options.show_belongs_to
|
120
|
+
|
121
|
+
# Only non standard association names needs a label
|
122
|
+
|
123
|
+
# from patch #12384
|
124
|
+
# if assoc.class_name == assoc.name.to_s.singularize.camelize
|
125
|
+
assoc_class_name = (assoc.class_name.respond_to? 'underscore') ? assoc.class_name.underscore.singularize.camelize : assoc.class_name
|
126
|
+
if assoc_class_name == assoc.name.to_s.singularize.camelize
|
127
|
+
assoc_name = ''
|
128
|
+
else
|
129
|
+
assoc_name = assoc.name.to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
if ['has_one', 'belongs_to'].include? assoc.macro.to_s
|
133
|
+
assoc_type = 'one-one'
|
134
|
+
elsif assoc.macro.to_s == 'has_many' && (! assoc.options[:through])
|
135
|
+
assoc_type = 'one-many'
|
136
|
+
else # habtm or has_many, :through
|
137
|
+
return if @habtm.include? [assoc.class_name, class_name, assoc_name]
|
138
|
+
assoc_type = 'many-many'
|
139
|
+
@habtm << [class_name, assoc.class_name, assoc_name]
|
140
|
+
end
|
141
|
+
# from patch #12384
|
142
|
+
# @graph.add_edge [assoc_type, class_name, assoc.class_name, assoc_name]
|
143
|
+
@graph.add_edge [assoc_type, class_name, assoc_class_name, assoc_name]
|
144
|
+
end # process_association
|
145
|
+
|
146
|
+
end # class ModelsDiagram
|
@@ -0,0 +1,178 @@
|
|
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
|
+
require 'ostruct'
|
8
|
+
|
9
|
+
# RailRoad command line options parser
|
10
|
+
class OptionsStruct < OpenStruct
|
11
|
+
|
12
|
+
require 'optparse'
|
13
|
+
|
14
|
+
def initialize(args={})
|
15
|
+
init_options = { :all => false,
|
16
|
+
:brief => false,
|
17
|
+
:specify => [],
|
18
|
+
:exclude => [],
|
19
|
+
:inheritance => false,
|
20
|
+
:join => false,
|
21
|
+
:label => false,
|
22
|
+
:modules => false,
|
23
|
+
:hide_magic => false,
|
24
|
+
:hide_types => false,
|
25
|
+
:hide_public => false,
|
26
|
+
:hide_protected => false,
|
27
|
+
:hide_private => false,
|
28
|
+
:plugins_models => false,
|
29
|
+
:root => '',
|
30
|
+
:show_belongs_to => false,
|
31
|
+
:transitive => false,
|
32
|
+
:verbose => false,
|
33
|
+
:xmi => false,
|
34
|
+
:command => '',
|
35
|
+
:app_name => 'railroad', :app_human_name => 'Railroad', :app_version =>'', :copyright =>'' }
|
36
|
+
super(init_options.merge(args))
|
37
|
+
end # initialize
|
38
|
+
|
39
|
+
def parse(args)
|
40
|
+
@opt_parser = OptionParser.new do |opts|
|
41
|
+
opts.banner = "Usage: #{self.app_name} [options] command"
|
42
|
+
opts.separator ""
|
43
|
+
opts.separator "Common options:"
|
44
|
+
opts.on("-b", "--brief", "Generate compact diagram",
|
45
|
+
" (no attributes nor methods)") do |b|
|
46
|
+
self.brief = b
|
47
|
+
end
|
48
|
+
opts.on("-s", "--specify file1[,fileN]", Array, "Specify only given files") do |list|
|
49
|
+
self.specify = list
|
50
|
+
end
|
51
|
+
opts.on("-e", "--exclude file1[,fileN]", Array, "Exclude given files") do |list|
|
52
|
+
self.exclude = list
|
53
|
+
end
|
54
|
+
opts.on("-i", "--inheritance", "Include inheritance relations") do |i|
|
55
|
+
self.inheritance = i
|
56
|
+
end
|
57
|
+
opts.on("-l", "--label", "Add a label with diagram information",
|
58
|
+
" (type, date, migration, version)") do |l|
|
59
|
+
self.label = l
|
60
|
+
end
|
61
|
+
opts.on("-o", "--output FILE", "Write diagram to file FILE") do |f|
|
62
|
+
self.output = f
|
63
|
+
end
|
64
|
+
opts.on("-r", "--root PATH", "Set PATH as the application root") do |r|
|
65
|
+
self.root = r
|
66
|
+
end
|
67
|
+
opts.on("-v", "--verbose", "Enable verbose output",
|
68
|
+
" (produce messages to STDOUT)") do |v|
|
69
|
+
self.verbose = v
|
70
|
+
end
|
71
|
+
opts.on("-x", "--xmi", "Produce XMI instead of DOT",
|
72
|
+
" (for UML tools)") do |x|
|
73
|
+
self.xmi = x
|
74
|
+
end
|
75
|
+
opts.separator ""
|
76
|
+
opts.separator "Models diagram options:"
|
77
|
+
opts.on("-a", "--all", "Include all models",
|
78
|
+
" (not only ActiveRecord::Base derived)") do |a|
|
79
|
+
self.all = a
|
80
|
+
end
|
81
|
+
opts.on("--show-belongs_to", "Show belongs_to associations") do |s|
|
82
|
+
self.show_belongs_to = s
|
83
|
+
end
|
84
|
+
opts.on("--hide-magic", "Hide magic field names") do |h|
|
85
|
+
self.hide_magic = h
|
86
|
+
end
|
87
|
+
opts.on("--hide-types", "Hide attributes type") do |h|
|
88
|
+
self.hide_types = h
|
89
|
+
end
|
90
|
+
opts.on("-j", "--join", "Concentrate edges") do |j|
|
91
|
+
self.join = j
|
92
|
+
end
|
93
|
+
opts.on("-m", "--modules", "Include modules") do |m|
|
94
|
+
self.modules = m
|
95
|
+
end
|
96
|
+
opts.on("-p", "--plugins-models", "Include plugins models") do |p|
|
97
|
+
self.plugins_models = p
|
98
|
+
end
|
99
|
+
opts.on("-t", "--transitive", "Include transitive associations",
|
100
|
+
"(through inheritance)") do |t|
|
101
|
+
self.transitive = t
|
102
|
+
end
|
103
|
+
opts.separator ""
|
104
|
+
opts.separator "Controllers diagram options:"
|
105
|
+
opts.on("--hide-public", "Hide public methods") do |h|
|
106
|
+
self.hide_public = h
|
107
|
+
end
|
108
|
+
opts.on("--hide-protected", "Hide protected methods") do |h|
|
109
|
+
self.hide_protected = h
|
110
|
+
end
|
111
|
+
opts.on("--hide-private", "Hide private methods") do |h|
|
112
|
+
self.hide_private = h
|
113
|
+
end
|
114
|
+
opts.separator ""
|
115
|
+
opts.separator "Other options:"
|
116
|
+
opts.on("-h", "--help", "Show this message") do
|
117
|
+
STDOUT.print "#{opts}\n"
|
118
|
+
exit
|
119
|
+
end
|
120
|
+
opts.on("--version", "Show version and copyright") do
|
121
|
+
STDOUT.print"#{self.app_human_name} version #{self.app_version}\n\n" +
|
122
|
+
"#{self.copyright}\nThis is free software; see the source " +
|
123
|
+
"for copying conditions.\n\n"
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
opts.separator ""
|
127
|
+
opts.separator "Commands (you must supply one of these):"
|
128
|
+
opts.on("-M", "--models", "Generate models diagram") do |c|
|
129
|
+
if self.command != ''
|
130
|
+
STDERR.print "Error: Can only generate one diagram type\n\n"
|
131
|
+
exit 1
|
132
|
+
else
|
133
|
+
self.command = 'models'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
opts.on("-C", "--controllers", "Generate controllers diagram") do |c|
|
137
|
+
if self.command != ''
|
138
|
+
STDERR.print "Error: Can only generate one diagram type\n\n"
|
139
|
+
exit 1
|
140
|
+
else
|
141
|
+
self.command = 'controllers'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
# From Ana Nelson's patch
|
145
|
+
opts.on("-A", "--aasm", "Generate \"acts as state machine\" diagram") do |c|
|
146
|
+
if self.command == 'controllers'
|
147
|
+
STDERR.print "Error: Can only generate one diagram type\n\n"
|
148
|
+
exit 1
|
149
|
+
else
|
150
|
+
self.command = 'aasm'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
opts.separator ""
|
154
|
+
opts.separator "For bug reporting and additional information, please see:"
|
155
|
+
opts.separator "http://railroad.rubyforge.org/"
|
156
|
+
end # do
|
157
|
+
|
158
|
+
begin
|
159
|
+
@opt_parser.parse!(args)
|
160
|
+
rescue OptionParser::AmbiguousOption
|
161
|
+
option_error "Ambiguous option"
|
162
|
+
rescue OptionParser::InvalidOption
|
163
|
+
option_error "Invalid option"
|
164
|
+
rescue OptionParser::InvalidArgument
|
165
|
+
option_error "Invalid argument"
|
166
|
+
rescue OptionParser::MissingArgument
|
167
|
+
option_error "Missing argument"
|
168
|
+
end
|
169
|
+
end # parse
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
def option_error(msg)
|
174
|
+
STDERR.print "Error: #{msg}\n\n #{@opt_parser}\n"
|
175
|
+
exit 1
|
176
|
+
end
|
177
|
+
|
178
|
+
end # class OptionsStruct
|