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.
@@ -17,36 +17,33 @@ class ModelsDiagram < AppDiagram
17
17
 
18
18
  # Process model files
19
19
  def generate
20
- STDERR.puts "Generating models diagram" if @options.verbose
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 #{$!} raised while trying to load model class #{f}"
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 + "app/models/**/*.rb")
33
- files += Dir.glob("vendor/plugins/**/app/models/*.rb") if @options.plugins_models
34
- files -= Dir.glob(prefix + "app/models/concerns/**/*.rb") unless @options.include_concerns
35
- files += get_engine_files if @options.engine_models
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 get_engine_files
41
- engines.collect { |engine| Dir.glob("#{engine.root.to_s}/app/models/**/*.rb")}.flatten
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.split('/').last.camelize.chomp(".rb")
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
- (defined?(CouchRest::Model::Base) && current_class.superclass != CouchRest::Model::Base) ||
79
- (current_class.superclass != Object)
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
- "created_at", "created_on", "updated_at", "updated_on",
108
- "lock_version", "type", "id", "position", "parent_id", "lft",
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| ! superclass_associations.include? 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 #|| current_class.abstract_class?
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
- ["created_at", "created_on", "updated_at", "updated_on", "lock_version", "_type", "_id",
157
- "position", "parent_id", "lft", "rgt", "quote", "template"]
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
- "created_at", "created_on", "updated_at", "updated_on",
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
- current_class.superclass.respond_to?(:relations)
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
- "created_at", "updated_at",
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.to_s}" if @options.verbose
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[belongs_to referenced_in].include?(macro) && !@options.show_belongs_to
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?("::") && !assoc_class_name.include?("::")
294
- assoc_class_name = class_name.split("::")[0..-2].push(assoc_class_name).join("::")
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!(%r{^::}, '')
280
+ assoc_class_name.gsub!(/^::/, '')
297
281
 
298
- if %w[has_one references_one embeds_one].include?(macro)
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[references_many embeds_many].include?(macro)
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.to_s}" if @options.verbose
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
- if !(relation.name.to_s.singularize.camelize.eql?(assoc_class_name.split('::').last))
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 = { :all => false,
16
- :brief => false,
17
- :specify => [],
18
- :exclude => [],
19
- :inheritance => false,
20
- :join => false,
21
- :label => false,
22
- :modules => false,
23
- :all_columns => false,
24
- :hide_magic => false,
25
- :hide_types => false,
26
- :hide_public => false,
27
- :hide_protected => false,
28
- :hide_private => false,
29
- :plugins_models => false,
30
- :engine_models => false,
31
- :engine_controllers => false,
32
- :include_concerns => false,
33
- :root => '',
34
- :show_belongs_to => false,
35
- :hide_through => false,
36
- :transitive => false,
37
- :verbose => false,
38
- :alphabetize => false,
39
- :xmi => false,
40
- :command => '',
41
- :config_file => 'config/environment',
42
- :app_name => 'railroady', :app_human_name => 'Railroady', :app_version =>'', :copyright =>'' }
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: #{self.app_name} [options] command"
49
- opts.separator ""
50
- opts.separator "Common options:"
51
- opts.on("-b", "--brief", "Generate compact diagram",
52
- " (no attributes nor methods)") do |b|
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("-s", "--specify file1[,fileN]", Array, "Specify only given files") do |list|
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("-e", "--exclude file1[,fileN]", Array, "Exclude given files") do |list|
57
+ opts.on('-e', '--exclude file1[,fileN]', Array, 'Exclude given files') do |list|
59
58
  self.exclude = list
60
59
  end
61
- opts.on("-i", "--inheritance", "Include inheritance relations") do |i|
60
+ opts.on('-i', '--inheritance', 'Include inheritance relations') do |i|
62
61
  self.inheritance = i
63
62
  end
64
- opts.on("-l", "--label", "Add a label with diagram information",
65
- " (type, date, migration, version)") do |l|
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("-o", "--output FILE", "Write diagram to file FILE") do |f|
67
+ opts.on('-o', '--output FILE', 'Write diagram to file FILE') do |f|
69
68
  self.output = f
70
69
  end
71
- opts.on("-r", "--root PATH", "Set PATH as the application root") do |r|
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("-v", "--verbose", "Enable verbose output",
75
- " (produce messages to STDOUT)") do |v|
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("-x", "--xmi", "Produce XMI instead of DOT",
79
- " (for UML tools)") do |x|
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("--alphabetize", "Sort methods alphabetically") do |a|
81
+ opts.on('--alphabetize', 'Sort methods alphabetically') do |a|
83
82
  self.alphabetize = a
84
83
  end
85
- opts.separator ""
86
- opts.separator "Models diagram options:"
87
- opts.on("-a", "--all", "Include all models",
88
- " (not only ActiveRecord::Base derived)") do |a|
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("--show-belongs_to", "Show belongs_to associations") do |s|
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("--hide-through", "Hide through associations") do |h|
93
+ opts.on('--hide-through', 'Hide through associations') do |h|
95
94
  self.hide_through = h
96
95
  end
97
- opts.on("--all-columns", "Show all columns (not just content columns)") do |h|
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("--hide-magic", "Hide magic field names") do |h|
99
+ opts.on('--hide-magic', 'Hide magic field names') do |h|
101
100
  self.hide_magic = h
102
101
  end
103
- opts.on("--hide-types", "Hide attributes type") do |h|
102
+ opts.on('--hide-types', 'Hide attributes type') do |h|
104
103
  self.hide_types = h
105
104
  end
106
- opts.on("-j", "--join", "Concentrate edges") do |j|
105
+ opts.on('-j', '--join', 'Concentrate edges') do |j|
107
106
  self.join = j
108
107
  end
109
- opts.on("-m", "--modules", "Include modules") do |m|
108
+ opts.on('-m', '--modules', 'Include modules') do |m|
110
109
  self.modules = m
111
110
  end
112
- opts.on("-p", "--plugins-models", "Include plugins models") do |p|
111
+ opts.on('-p', '--plugins-models', 'Include plugins models') do |p|
113
112
  self.plugins_models = p
114
113
  end
115
- opts.on("-z", "--engine-models", "Include engine models") do |em|
114
+ opts.on('-z', '--engine-models', 'Include engine models') do |em|
116
115
  self.engine_models = em
117
116
  end
118
- opts.on("--include-concerns", "Include models in concerns subdirectory") do |c|
117
+ opts.on('--include-concerns', 'Include models in concerns subdirectory') do |c|
119
118
  self.include_concerns = c
120
119
  end
121
- opts.on("-t", "--transitive", "Include transitive associations",
122
- "(through inheritance)") do |t|
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 "Controllers diagram options:"
127
- opts.on("--hide-public", "Hide public methods") do |h|
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("--hide-protected", "Hide protected methods") do |h|
129
+ opts.on('--hide-protected', 'Hide protected methods') do |h|
131
130
  self.hide_protected = h
132
131
  end
133
- opts.on("--hide-private", "Hide private methods") do |h|
132
+ opts.on('--hide-private', 'Hide private methods') do |h|
134
133
  self.hide_private = h
135
134
  end
136
- opts.on("--engine-controllers", "Include engine controllers") do |ec|
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 "Other options:"
141
- opts.on("-h", "--help", "Show this message") do
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("--version", "Show version and copyright") do
146
- STDOUT.print"#{self.app_human_name} version #{self.app_version}\n\n" +
147
- "#{self.copyright}\nThis is free software; see the source " +
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("-c", "--config FILE", "File to load environment (defaults to config/environment)") do |c|
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 "Commands (you must supply one of these):"
158
- opts.on("-M", "--models", "Generate models diagram") do |c|
159
- if self.command != ''
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("-C", "--controllers", "Generate controllers diagram") do |c|
167
- if self.command != ''
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("-A", "--aasm", "Generate \"acts as state machine\" diagram") do |c|
176
- if self.command == 'controllers'
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 "For bug reporting and additional information, please see:"
185
- opts.separator "http://railroad.rubyforge.org/"
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 "Ambiguous option"
188
+ option_error 'Ambiguous option'
192
189
  rescue OptionParser::InvalidOption
193
- option_error "Invalid option"
190
+ option_error 'Invalid option'
194
191
  rescue OptionParser::InvalidArgument
195
- option_error "Invalid argument"
192
+ option_error 'Invalid argument'
196
193
  rescue OptionParser::MissingArgument
197
- option_error "Missing argument"
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