OptionParser does not enforce required argument

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:increateFile’
from ./itos_logs_dms.rb:75:in `’

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:inblock 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:inparse_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:inpermute!’
from /usr/local/lib/ruby/1.9.1/optparse.rb:1364:in parse!' from ./itos_logs_dms.rb:25:inparse’
from ./itos_logs_dms.rb:75:in `’

<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:inblock 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:inparse_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:inpermute!’
from /usr/local/lib/ruby/1.9.1/optparse.rb:1364:in parse!' from ./itos_logs_dms.rb:25:inparse’
from ./itos_logs_dms.rb:75:in `’

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

Thank you for your help in advance.

On 02/09/2010 08:22 PM, Sean Smitz wrote:

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 `’
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