OptionParser does not enforce required argument

S

Sean Smitz

I'm not seeing the difference between specifying a required argument and
an option argument in OptionParser other than they used '<<' in the
assignment of the former. When I don't give an output_file it runs fine
until it needs to use the filename and then gives a nil error. When I do
specify the filename I get an error for using the '<<' operator. Command
line output for both cases given below the code:

def self.parse(args)
options = OpenStruct.new
String usage = "Usage: itos_logs_dms -o <output_file>
[Options]\n\nThe following script is used to filter a set of ITOS log
messages from the log\ndatabase and format them for parsing by
Attention!. The fields will be tab\ndelineated and any tabs in the ITOS
event message will be replaced by 8 spaces.\n"

opts = OptionParser.new do |opts|
opts.banner = usage
opts.separator ""
opts.separator "Specific options:"

//This is supposed to be the required argument
opts.on("-o", "--output OUTPUT_FILE", String, "Name of
OUTPUT_FILE is a required argument.") do |o| options.output_file << o
end

opts.on("-i", "--tag_id [TAG_ID]", String, "Retrieves only
the messages that are tagged with the given tag_id.") do |i|
options.tag_id = i end
opts.on("-s", "--severity [SEVERITY]", Integer, "Retrieves
only the messages that are >= the given severity (0-5).") do |s|
options.severity = s end
opts.on("-t", "--timestamp [TIMESTAMP]", Time, "Retrieves
only the messages that are >= the given timestamp (yyyy-mm-dd
HH:mm:ss.SS)") do |t| options.timestamp = t end
opts.separator "Common options:"
opts.on_tail("-h", "--help", "Show this message.") do puts
opts exit end
end

opts.parse!(args)
options
end

# No Option Given:
<stsmitz@ptolemy-redhati386 ~> ./itos_logs_dms.rb
/itos_logs_dms.rb:45:in `+': can't convert nil into String (TypeError)
from ./itos_logs_dms.rb:45:in `createFile'
from ./itos_logs_dms.rb:75:in `<main>'

# Option provided (two ways):
<stsmitz@ptolemy-redhati386 ~> ./itos_logs_dms.rb --output log_test1
/itos_logs_dms.rb:17:in `block (2 levels) in parse': undefined method
`<<' for nil:NilClass (NoMethodError)
from /usr/local/lib/ruby/1.9.1/optparse.rb:1271:in `call'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1271:in `block in
parse_in_order'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1258:in `catch'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1258:in
`parse_in_order'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1252:in `order!'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1343:in `permute!'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1364:in `parse!'
from ./itos_logs_dms.rb:25:in `parse'
from ./itos_logs_dms.rb:75:in `<main>'


<stsmitz@ptolemy-redhati386 ~> ./itos_logs_dms.rb -o log_test1
/itos_logs_dms.rb:17:in `block (2 levels) in parse': undefined method
`<<' for nil:NilClass (NoMethodError)
from /usr/local/lib/ruby/1.9.1/optparse.rb:1302:in `call'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1302:in `block in
parse_in_order'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1258:in `catch'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1258:in
`parse_in_order'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1252:in `order!'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1343:in `permute!'
from /usr/local/lib/ruby/1.9.1/optparse.rb:1364:in `parse!'
from ./itos_logs_dms.rb:25:in `parse'
from ./itos_logs_dms.rb:75:in `<main>'

<stsmitz@ptolemy-redhati386 ~> ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i686-linux]

Thank you for your help in advance.
 
R

Robert Klemme

I'm not seeing the difference between specifying a required argument and
an option argument in OptionParser other than they used '<<' in the
assignment of the former.

"Mandatory" refers to the argument to an option - not the presence of
the option as such.

Quoting the docs

# Mandatory argument.
opts.on("-r", "--require LIBRARY",
"Require the LIBRARY before executing your script") do
|lib|
options.library << lib
end

# Optional argument; multi-line description.
opts.on("-i", "--inplace [EXTENSION]",
"Edit ARGV files in place",
" (make backup if EXTENSION supplied)") do |ext|
options.inplace = true
options.extension = ext || ''
options.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension
begins with dot.
end

Option -r needs an argument (the library) while option -i can go
without. Example:

irb(main):004:0> OptionParser.new do |o|
irb(main):005:1* o.on '-i NAME' do |x| p x end
irb(main):006:1> end.parse ["-i", "xx"]
"xx"
=> []
irb(main):007:0> OptionParser.new do |o|
irb(main):008:1* o.on '-i NAME' do |x| p x end
irb(main):009:1> end.parse ["-i"]
OptionParser::MissingArgument: missing argument: -i
from (irb):7
from /usr/local/bin/irb19:12:in `<main>'
irb(main):010:0> OptionParser.new do |o|
irb(main):011:1* o.on '-i [NAME]' do |x| p x end
irb(main):012:1> end.parse ["-i"]
nil
=> []
irb(main):013:0>

If you want to ensure that an option is present (which is somewhat
contradictory, there is a reason they are called "options") you can
assign the argument (or a value provided) to a variable and check that
variable for nil after option processing.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top