Trevor Burnham
Trevor Burnham

Reputation: 77416

Can I use Ruby's OptionParser to accept an arbitrary argument pattern?

Let's say that I have a simple Ruby app where I want the first argument (if any) to specify the environment: TEST, DEVELOPMENT or PRODUCTION (with DEVELOPMENT being the default if no argument is given). For instance,

ruby myapp.rb test

would run it in TEST mode. Also, shorthands should be accepted, so that for instance

ruby myapp.rb t

would run the app in TEST mode and

ruby myapp.rb dev

would run it in DEVELOPMENT mode.

I'd like to use OptionParser, but it behaves very weirdly. If myapp.rb is

require 'optparse'

environment = 'DEVELOPMENT'
opts = OptionParser.new
opts.on('test')        { environment = 'TEST' }
opts.on('production')  { environment = 'PRODUCTION' }
opts.parse!(ARGV)

then environment becomes PRODUCTION no matter what arguments I pass; for some reason, opts.on('production') always executes its block. (It doesn't if I use a flag-style string like '-production' instead.) And there's no way I can see to have OptionParser look for strings starting with 't' rather than the exact string 'test'.

Maybe OptionParser is the wrong tool for the job. Obviously it would be trivial to split up ARGV myself. I'm just wondering what's going on with this behavior. I'm on Ruby 1.9.2.

Upvotes: 2

Views: 1005

Answers (2)

Chris
Chris

Reputation: 11

Provided you use the parse! method, any arguments handled by opts.on calls are stripped from the ARGV array destructively. This means that the original contents of the ARGV array will no longer contain those flags after the parse! method.

I recommend parsing the remaining set of arguments manually by comparing ARGV to an array containing 'test' and 'production'.

Check out the doc: http://ruby-doc.org/stdlib-1.9.3/libdoc/optparse/rdoc/OptionParser.html#method-i-parse-21

Upvotes: 1

Blaine Lafreniere
Blaine Lafreniere

Reputation: 3600

I'd say you need to parse out arguments like that from ARGV before running OptionParser

e.g.

env = ARGV.select{|arg| arg =~ /dev/test/prod/i}.first

P.S. I'd recommend Trollop. I find it much simpler, and it's good about picking defaults.

Upvotes: 0

Related Questions