railroady 1.3.0 → 1.3.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.
- checksums.yaml +4 -4
- data/Guardfile +0 -1
- data/Rakefile +5 -5
- data/bin/railroady +6 -7
- data/lib/railroady.rb +2 -2
- data/lib/railroady/aasm_diagram.rb +24 -29
- data/lib/railroady/app_diagram.rb +16 -23
- data/lib/railroady/controllers_diagram.rb +33 -40
- data/lib/railroady/diagram_graph.rb +45 -55
- data/lib/railroady/models_diagram.rb +37 -56
- data/lib/railroady/options_struct.rb +99 -103
- data/lib/railroady/railtie.rb +4 -5
- data/lib/railroady/version.rb +1 -1
- data/railroady.gemspec +12 -13
- data/tasks/railroady.rake +20 -29
- data/test/file_fixture/app/controllers/application_controller.rb +1 -1
- data/test/lib/railroady/aasm_diagram_spec.rb +14 -16
- data/test/lib/railroady/app_diagram_spec.rb +1 -2
- data/test/lib/railroady/controllers_diagram_spec.rb +16 -19
- data/test/lib/railroady/core_ext_spec.rb +2 -2
- data/test/lib/railroady/diagram_graph_spec.rb +6 -2
- data/test/lib/railroady/models_diagram_spec.rb +18 -20
- data/test/spec_helper.rb +1 -1
- metadata +4 -3
@@ -17,36 +17,33 @@ class ModelsDiagram < AppDiagram
|
|
17
17
|
|
18
18
|
# Process model files
|
19
19
|
def generate
|
20
|
-
STDERR.puts
|
20
|
+
STDERR.puts 'Generating models diagram' if @options.verbose
|
21
21
|
get_files.each do |f|
|
22
22
|
begin
|
23
23
|
process_class extract_class_name(f).constantize
|
24
24
|
rescue Exception
|
25
|
-
STDERR.puts "Warning: exception #{
|
25
|
+
STDERR.puts "Warning: exception #{$ERROR_INFO} raised while trying to load model class #{f}"
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
|
-
def get_files(prefix ='')
|
32
|
-
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix +
|
33
|
-
files += Dir.glob(
|
34
|
-
files -= Dir.glob(prefix +
|
35
|
-
files +=
|
30
|
+
def get_files(prefix = '')
|
31
|
+
files = !@options.specify.empty? ? Dir.glob(@options.specify) : Dir.glob(prefix + 'app/models/**/*.rb')
|
32
|
+
files += Dir.glob('vendor/plugins/**/app/models/*.rb') if @options.plugins_models
|
33
|
+
files -= Dir.glob(prefix + 'app/models/concerns/**/*.rb') unless @options.include_concerns
|
34
|
+
files += engine_files if @options.engine_models
|
36
35
|
files -= Dir.glob(@options.exclude)
|
37
36
|
files
|
38
37
|
end
|
39
38
|
|
40
|
-
def
|
41
|
-
engines.collect { |engine| Dir.glob("#{engine.root
|
39
|
+
def engine_files
|
40
|
+
engines.collect { |engine| Dir.glob("#{engine.root}/app/models/**/*.rb") }.flatten
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
43
|
def extract_class_name(filename)
|
46
|
-
filename.
|
44
|
+
filename.match(/.*\/models\/(.*).rb$/)[1].camelize
|
47
45
|
end
|
48
46
|
|
49
|
-
|
50
47
|
# Process a model class
|
51
48
|
def process_class(current_class)
|
52
49
|
STDERR.puts "Processing #{current_class}" if @options.verbose
|
@@ -58,7 +55,7 @@ class ModelsDiagram < AppDiagram
|
|
58
55
|
process_mongoid_model(current_class)
|
59
56
|
elsif defined?(DataMapper::Resource) && current_class.new.is_a?(DataMapper::Resource)
|
60
57
|
process_datamapper_model(current_class)
|
61
|
-
elsif current_class.respond_to?'reflect_on_all_associations'
|
58
|
+
elsif current_class.respond_to? 'reflect_on_all_associations'
|
62
59
|
process_active_record_model(current_class)
|
63
60
|
elsif @options.all && (current_class.is_a? Class)
|
64
61
|
process_basic_class(current_class)
|
@@ -69,14 +66,13 @@ class ModelsDiagram < AppDiagram
|
|
69
66
|
if @options.inheritance && generated && include_inheritance?(current_class)
|
70
67
|
@graph.add_edge ['is-a', current_class.superclass.name, current_class.name]
|
71
68
|
end
|
72
|
-
|
73
69
|
end # process_class
|
74
70
|
|
75
71
|
def include_inheritance?(current_class)
|
76
72
|
STDERR.puts current_class.superclass if @options.verbose
|
77
73
|
(defined?(ActiveRecord::Base) && current_class.superclass != ActiveRecord::Base) ||
|
78
|
-
|
79
|
-
|
74
|
+
(defined?(CouchRest::Model::Base) && current_class.superclass != CouchRest::Model::Base) ||
|
75
|
+
(current_class.superclass != Object)
|
80
76
|
end
|
81
77
|
|
82
78
|
def process_basic_class(current_class)
|
@@ -98,18 +94,14 @@ class ModelsDiagram < AppDiagram
|
|
98
94
|
node_type = 'model'
|
99
95
|
|
100
96
|
# Collect model's content columns
|
101
|
-
#content_columns = current_class.content_columns
|
97
|
+
# content_columns = current_class.content_columns
|
102
98
|
|
103
99
|
if @options.hide_magic
|
104
100
|
# From patch #13351
|
105
101
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
106
|
-
magic_fields =
|
107
|
-
|
108
|
-
|
109
|
-
"rgt", "quote", "template"
|
110
|
-
]
|
111
|
-
magic_fields << current_class.table_name + "_count" if current_class.respond_to? 'table_name'
|
112
|
-
content_columns = current_class.content_columns.select {|c| ! magic_fields.include? c.name}
|
102
|
+
magic_fields = %w(created_at created_on updated_at updated_on lock_version type id position parent_id lft rgt quote template)
|
103
|
+
magic_fields << current_class.table_name + '_count' if current_class.respond_to? 'table_name'
|
104
|
+
content_columns = current_class.content_columns.select { |c| !magic_fields.include? c.name }
|
113
105
|
else
|
114
106
|
content_columns = current_class.columns
|
115
107
|
end
|
@@ -127,7 +119,7 @@ class ModelsDiagram < AppDiagram
|
|
127
119
|
if @options.inheritance && ! @options.transitive
|
128
120
|
superclass_associations = current_class.superclass.reflect_on_all_associations
|
129
121
|
|
130
|
-
associations = associations.select{|a| !
|
122
|
+
associations = associations.select { |a| !superclass_associations.include? a }
|
131
123
|
# This doesn't works!
|
132
124
|
# associations -= current_class.superclass.reflect_on_all_associations
|
133
125
|
end
|
@@ -141,7 +133,7 @@ class ModelsDiagram < AppDiagram
|
|
141
133
|
|
142
134
|
def process_datamapper_model(current_class)
|
143
135
|
node_attribs = []
|
144
|
-
if @options.brief
|
136
|
+
if @options.brief # || current_class.abstract_class?
|
145
137
|
node_type = 'model-brief'
|
146
138
|
else
|
147
139
|
node_type = 'model'
|
@@ -153,9 +145,8 @@ class ModelsDiagram < AppDiagram
|
|
153
145
|
# From patch #13351
|
154
146
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
155
147
|
magic_fields =
|
156
|
-
|
157
|
-
|
158
|
-
props = props.select {|c| !magic_fields.include?(c.name.to_s) }
|
148
|
+
%w(created_at created_on updated_at updated_on lock_version _type _id position parent_id lft rgt quote template)
|
149
|
+
props = props.select { |c| !magic_fields.include?(c.name.to_s) }
|
159
150
|
end
|
160
151
|
|
161
152
|
props.each do |a|
|
@@ -192,12 +183,8 @@ class ModelsDiagram < AppDiagram
|
|
192
183
|
if @options.hide_magic
|
193
184
|
# From patch #13351
|
194
185
|
# http://wiki.rubyonrails.org/rails/pages/MagicFieldNames
|
195
|
-
magic_fields =
|
196
|
-
|
197
|
-
"lock_version", "_type", "_id", "position", "parent_id", "lft",
|
198
|
-
"rgt", "quote", "template"
|
199
|
-
]
|
200
|
-
content_columns = content_columns.select {|c| !magic_fields.include?(c.name) }
|
186
|
+
magic_fields = %w(created_at created_on updated_at updated_on lock_version _type _id position parent_id lft rgt quote template)
|
187
|
+
content_columns = content_columns.select { |c| !magic_fields.include?(c.name) }
|
201
188
|
end
|
202
189
|
|
203
190
|
content_columns.each do |a|
|
@@ -213,7 +200,7 @@ class ModelsDiagram < AppDiagram
|
|
213
200
|
associations = current_class.relations.values
|
214
201
|
|
215
202
|
if @options.inheritance && !@options.transitive &&
|
216
|
-
|
203
|
+
current_class.superclass.respond_to?(:relations)
|
217
204
|
associations -= current_class.superclass.relations.values
|
218
205
|
end
|
219
206
|
|
@@ -242,11 +229,8 @@ class ModelsDiagram < AppDiagram
|
|
242
229
|
content_columns = current_class.properties
|
243
230
|
|
244
231
|
if @options.hide_magic
|
245
|
-
magic_fields =
|
246
|
-
|
247
|
-
"type", "_id", "_rev"
|
248
|
-
]
|
249
|
-
content_columns = content_columns.select {|c| !magic_fields.include?(c.name) }
|
232
|
+
magic_fields = %w(created_at updated_at type _id _rev)
|
233
|
+
content_columns = content_columns.select { |c| !magic_fields.include?(c.name) }
|
250
234
|
end
|
251
235
|
|
252
236
|
content_columns.each do |a|
|
@@ -263,17 +247,17 @@ class ModelsDiagram < AppDiagram
|
|
263
247
|
|
264
248
|
# Process a model association
|
265
249
|
def process_association(class_name, assoc)
|
266
|
-
STDERR.puts "- Processing model association #{assoc.name
|
250
|
+
STDERR.puts "- Processing model association #{assoc.name}" if @options.verbose
|
267
251
|
|
268
252
|
# Skip "belongs_to" associations
|
269
253
|
macro = assoc.macro.to_s
|
270
|
-
return if %w
|
254
|
+
return if %w(belongs_to referenced_in).include?(macro) && !@options.show_belongs_to
|
271
255
|
|
272
256
|
# Skip "through" associations
|
273
257
|
through = assoc.options.include?(:through)
|
274
258
|
return if through && @options.hide_through
|
275
259
|
|
276
|
-
#TODO:
|
260
|
+
# TODO:
|
277
261
|
# FAIL: assoc.methods.include?(:class_name)
|
278
262
|
# FAIL: assoc.responds_to?(:class_name)
|
279
263
|
assoc_class_name = assoc.class_name rescue nil
|
@@ -290,15 +274,15 @@ class ModelsDiagram < AppDiagram
|
|
290
274
|
end
|
291
275
|
|
292
276
|
# Patch from "alpack" to support classes in a non-root module namespace. See: http://disq.us/yxl1v
|
293
|
-
if class_name.include?(
|
294
|
-
assoc_class_name = class_name.split(
|
277
|
+
if class_name.include?('::') && !assoc_class_name.include?('::')
|
278
|
+
assoc_class_name = class_name.split('::')[0..-2].push(assoc_class_name).join('::')
|
295
279
|
end
|
296
|
-
assoc_class_name.gsub!(
|
280
|
+
assoc_class_name.gsub!(/^::/, '')
|
297
281
|
|
298
|
-
if %w
|
282
|
+
if %w(has_one references_one embeds_one).include?(macro)
|
299
283
|
assoc_type = 'one-one'
|
300
284
|
elsif macro == 'has_many' && (!assoc.options[:through]) ||
|
301
|
-
%w
|
285
|
+
%w(references_many embeds_many).include?(macro)
|
302
286
|
assoc_type = 'one-many'
|
303
287
|
else # habtm or has_many, :through
|
304
288
|
# Add FAKE associations too in order to understand mistakes
|
@@ -313,7 +297,7 @@ class ModelsDiagram < AppDiagram
|
|
313
297
|
|
314
298
|
# Process a DataMapper relationship
|
315
299
|
def process_datamapper_relationship(class_name, relation)
|
316
|
-
STDERR.puts "- Processing DataMapper model relationship #{relation.name
|
300
|
+
STDERR.puts "- Processing DataMapper model relationship #{relation.name}" if @options.verbose
|
317
301
|
|
318
302
|
# Skip "belongs_to" relationships
|
319
303
|
dm_type = relation.class.to_s.split('::')[-2]
|
@@ -332,7 +316,7 @@ class ModelsDiagram < AppDiagram
|
|
332
316
|
|
333
317
|
# Only non standard association names needs a label
|
334
318
|
assoc_name = ''
|
335
|
-
|
319
|
+
unless relation.name.to_s.singularize.camelize.eql?(assoc_class_name.split('::').last)
|
336
320
|
assoc_name = relation.name.to_s
|
337
321
|
end
|
338
322
|
|
@@ -344,9 +328,6 @@ class ModelsDiagram < AppDiagram
|
|
344
328
|
rel_type = 'one-many'
|
345
329
|
end
|
346
330
|
|
347
|
-
@graph.add_edge [rel_type, class_name, assoc_class_name, assoc_name
|
331
|
+
@graph.add_edge [rel_type, class_name, assoc_class_name, assoc_name]
|
348
332
|
end
|
349
|
-
|
350
333
|
end # class ModelsDiagram
|
351
|
-
|
352
|
-
|
@@ -8,201 +8,197 @@ require 'ostruct'
|
|
8
8
|
|
9
9
|
# RailRoady command line options parser
|
10
10
|
class OptionsStruct < OpenStruct
|
11
|
-
|
12
11
|
require 'optparse'
|
13
12
|
|
14
|
-
def initialize(args={})
|
15
|
-
init_options = { :
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
13
|
+
def initialize(args = {})
|
14
|
+
init_options = { all: false,
|
15
|
+
brief: false,
|
16
|
+
specify: [],
|
17
|
+
exclude: [],
|
18
|
+
inheritance: false,
|
19
|
+
join: false,
|
20
|
+
label: false,
|
21
|
+
modules: false,
|
22
|
+
all_columns: 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
|
+
engine_models: false,
|
30
|
+
engine_controllers: false,
|
31
|
+
include_concerns: false,
|
32
|
+
root: '',
|
33
|
+
show_belongs_to: false,
|
34
|
+
hide_through: false,
|
35
|
+
transitive: false,
|
36
|
+
verbose: false,
|
37
|
+
alphabetize: false,
|
38
|
+
xmi: false,
|
39
|
+
command: '',
|
40
|
+
config_file: 'config/environment',
|
41
|
+
app_name: 'railroady', app_human_name: 'Railroady', app_version: '', copyright: '' }
|
43
42
|
super(init_options.merge(args))
|
44
43
|
end # initialize
|
45
44
|
|
46
45
|
def parse(args)
|
47
46
|
@opt_parser = OptionParser.new do |opts|
|
48
|
-
opts.banner = "Usage: #{
|
49
|
-
opts.separator
|
50
|
-
opts.separator
|
51
|
-
opts.on(
|
52
|
-
|
47
|
+
opts.banner = "Usage: #{app_name} [options] command"
|
48
|
+
opts.separator ''
|
49
|
+
opts.separator 'Common options:'
|
50
|
+
opts.on('-b', '--brief', 'Generate compact diagram',
|
51
|
+
' (no attributes nor methods)') do |b|
|
53
52
|
self.brief = b
|
54
53
|
end
|
55
|
-
opts.on(
|
54
|
+
opts.on('-s', '--specify file1[,fileN]', Array, 'Specify only given files') do |list|
|
56
55
|
self.specify = list
|
57
56
|
end
|
58
|
-
opts.on(
|
57
|
+
opts.on('-e', '--exclude file1[,fileN]', Array, 'Exclude given files') do |list|
|
59
58
|
self.exclude = list
|
60
59
|
end
|
61
|
-
opts.on(
|
60
|
+
opts.on('-i', '--inheritance', 'Include inheritance relations') do |i|
|
62
61
|
self.inheritance = i
|
63
62
|
end
|
64
|
-
opts.on(
|
65
|
-
|
63
|
+
opts.on('-l', '--label', 'Add a label with diagram information',
|
64
|
+
' (type, date, migration, version)') do |l|
|
66
65
|
self.label = l
|
67
66
|
end
|
68
|
-
opts.on(
|
67
|
+
opts.on('-o', '--output FILE', 'Write diagram to file FILE') do |f|
|
69
68
|
self.output = f
|
70
69
|
end
|
71
|
-
opts.on(
|
70
|
+
opts.on('-r', '--root PATH', 'Set PATH as the application root') do |r|
|
72
71
|
self.root = r
|
73
72
|
end
|
74
|
-
opts.on(
|
75
|
-
|
73
|
+
opts.on('-v', '--verbose', 'Enable verbose output',
|
74
|
+
' (produce messages to STDOUT)') do |v|
|
76
75
|
self.verbose = v
|
77
76
|
end
|
78
|
-
opts.on(
|
79
|
-
|
77
|
+
opts.on('-x', '--xmi', 'Produce XMI instead of DOT',
|
78
|
+
' (for UML tools)') do |x|
|
80
79
|
self.xmi = x
|
81
80
|
end
|
82
|
-
opts.on(
|
81
|
+
opts.on('--alphabetize', 'Sort methods alphabetically') do |a|
|
83
82
|
self.alphabetize = a
|
84
83
|
end
|
85
|
-
opts.separator
|
86
|
-
opts.separator
|
87
|
-
opts.on(
|
88
|
-
|
84
|
+
opts.separator ''
|
85
|
+
opts.separator 'Models diagram options:'
|
86
|
+
opts.on('-a', '--all', 'Include all models',
|
87
|
+
' (not only ActiveRecord::Base derived)') do |a|
|
89
88
|
self.all = a
|
90
89
|
end
|
91
|
-
opts.on(
|
90
|
+
opts.on('--show-belongs_to', 'Show belongs_to associations') do |s|
|
92
91
|
self.show_belongs_to = s
|
93
92
|
end
|
94
|
-
opts.on(
|
93
|
+
opts.on('--hide-through', 'Hide through associations') do |h|
|
95
94
|
self.hide_through = h
|
96
95
|
end
|
97
|
-
opts.on(
|
96
|
+
opts.on('--all-columns', 'Show all columns (not just content columns)') do |h|
|
98
97
|
self.all_columns = h
|
99
98
|
end
|
100
|
-
opts.on(
|
99
|
+
opts.on('--hide-magic', 'Hide magic field names') do |h|
|
101
100
|
self.hide_magic = h
|
102
101
|
end
|
103
|
-
opts.on(
|
102
|
+
opts.on('--hide-types', 'Hide attributes type') do |h|
|
104
103
|
self.hide_types = h
|
105
104
|
end
|
106
|
-
opts.on(
|
105
|
+
opts.on('-j', '--join', 'Concentrate edges') do |j|
|
107
106
|
self.join = j
|
108
107
|
end
|
109
|
-
opts.on(
|
108
|
+
opts.on('-m', '--modules', 'Include modules') do |m|
|
110
109
|
self.modules = m
|
111
110
|
end
|
112
|
-
opts.on(
|
111
|
+
opts.on('-p', '--plugins-models', 'Include plugins models') do |p|
|
113
112
|
self.plugins_models = p
|
114
113
|
end
|
115
|
-
opts.on(
|
114
|
+
opts.on('-z', '--engine-models', 'Include engine models') do |em|
|
116
115
|
self.engine_models = em
|
117
116
|
end
|
118
|
-
opts.on(
|
117
|
+
opts.on('--include-concerns', 'Include models in concerns subdirectory') do |c|
|
119
118
|
self.include_concerns = c
|
120
119
|
end
|
121
|
-
opts.on(
|
122
|
-
|
120
|
+
opts.on('-t', '--transitive', 'Include transitive associations',
|
121
|
+
'(through inheritance)') do |t|
|
123
122
|
self.transitive = t
|
124
123
|
end
|
125
|
-
opts.separator
|
126
|
-
opts.separator
|
127
|
-
opts.on(
|
124
|
+
opts.separator ''
|
125
|
+
opts.separator 'Controllers diagram options:'
|
126
|
+
opts.on('--hide-public', 'Hide public methods') do |h|
|
128
127
|
self.hide_public = h
|
129
128
|
end
|
130
|
-
opts.on(
|
129
|
+
opts.on('--hide-protected', 'Hide protected methods') do |h|
|
131
130
|
self.hide_protected = h
|
132
131
|
end
|
133
|
-
opts.on(
|
132
|
+
opts.on('--hide-private', 'Hide private methods') do |h|
|
134
133
|
self.hide_private = h
|
135
134
|
end
|
136
|
-
opts.on(
|
135
|
+
opts.on('--engine-controllers', 'Include engine controllers') do |ec|
|
137
136
|
self.engine_controllers = ec
|
138
137
|
end
|
139
|
-
opts.separator
|
140
|
-
opts.separator
|
141
|
-
opts.on(
|
138
|
+
opts.separator ''
|
139
|
+
opts.separator 'Other options:'
|
140
|
+
opts.on('-h', '--help', 'Show this message') do
|
142
141
|
STDOUT.print "#{opts}\n"
|
143
142
|
exit
|
144
143
|
end
|
145
|
-
opts.on(
|
146
|
-
STDOUT.print"#{
|
147
|
-
"#{
|
144
|
+
opts.on('--version', 'Show version and copyright') do
|
145
|
+
STDOUT.print "#{app_human_name} version #{app_version}\n\n" \
|
146
|
+
"#{copyright}\nThis is free software; see the source " \
|
148
147
|
"for copying conditions.\n\n"
|
149
148
|
exit
|
150
149
|
end
|
151
|
-
opts.separator
|
152
|
-
opts.on(
|
153
|
-
if c && c != ''
|
154
|
-
self.config_file = c
|
155
|
-
end
|
150
|
+
opts.separator ''
|
151
|
+
opts.on('-c', '--config FILE', 'File to load environment (defaults to config/environment)') do |c|
|
152
|
+
self.config_file = c if c && c != ''
|
156
153
|
end
|
157
|
-
opts.separator
|
158
|
-
opts.on(
|
159
|
-
if
|
154
|
+
opts.separator 'Commands (you must supply one of these):'
|
155
|
+
opts.on('-M', '--models', 'Generate models diagram') do |_c|
|
156
|
+
if command != ''
|
160
157
|
STDERR.print "Error: Can only generate one diagram type\n\n"
|
161
158
|
exit 1
|
162
|
-
else
|
163
|
-
self.command = 'models'
|
159
|
+
else
|
160
|
+
self.command = 'models'
|
164
161
|
end
|
165
|
-
end
|
166
|
-
opts.on(
|
167
|
-
if
|
162
|
+
end
|
163
|
+
opts.on('-C', '--controllers', 'Generate controllers diagram') do |_c|
|
164
|
+
if command != ''
|
168
165
|
STDERR.print "Error: Can only generate one diagram type\n\n"
|
169
166
|
exit 1
|
170
|
-
else
|
171
|
-
self.command = 'controllers'
|
167
|
+
else
|
168
|
+
self.command = 'controllers'
|
172
169
|
end
|
173
170
|
end
|
174
171
|
# From Ana Nelson's patch
|
175
|
-
opts.on(
|
176
|
-
if
|
172
|
+
opts.on('-A', '--aasm', "Generate \"acts as state machine\" diagram") do |_c|
|
173
|
+
if command == 'controllers'
|
177
174
|
STDERR.print "Error: Can only generate one diagram type\n\n"
|
178
175
|
exit 1
|
179
|
-
else
|
176
|
+
else
|
180
177
|
self.command = 'aasm'
|
181
178
|
end
|
182
|
-
end
|
183
|
-
opts.separator
|
184
|
-
opts.separator
|
185
|
-
opts.separator
|
179
|
+
end
|
180
|
+
opts.separator ''
|
181
|
+
opts.separator 'For bug reporting and additional information, please see:'
|
182
|
+
opts.separator 'http://railroad.rubyforge.org/'
|
186
183
|
end # do
|
187
184
|
|
188
185
|
begin
|
189
186
|
@opt_parser.parse!(args)
|
190
187
|
rescue OptionParser::AmbiguousOption
|
191
|
-
option_error
|
188
|
+
option_error 'Ambiguous option'
|
192
189
|
rescue OptionParser::InvalidOption
|
193
|
-
option_error
|
190
|
+
option_error 'Invalid option'
|
194
191
|
rescue OptionParser::InvalidArgument
|
195
|
-
option_error
|
192
|
+
option_error 'Invalid argument'
|
196
193
|
rescue OptionParser::MissingArgument
|
197
|
-
option_error
|
194
|
+
option_error 'Missing argument'
|
198
195
|
end
|
199
196
|
end # parse
|
200
197
|
|
201
|
-
private
|
198
|
+
private
|
202
199
|
|
203
200
|
def option_error(msg)
|
204
201
|
STDERR.print "Error: #{msg}\n\n #{@opt_parser}\n"
|
205
202
|
exit 1
|
206
203
|
end
|
207
|
-
|
208
204
|
end # class OptionsStruct
|