Program Arguments in Ruby II: OptionParser
Here is a link to my last medium post:
Program Arguments in Ruby: Part I
In this article we’re going to explore the following topics:
- the
OptionParser
class OptionParser#on
methodOptionParser#on
and type coercion
The OptionParser class
OptionParser
is a class that eases the parsing and the interpretation of command-line options.
This class provides a bunch of methods to handle banners, option help messages, type coercion, etc…
OptionParser#on
OptionParser#on
adds a switch associated with a handler to the parser.
A switch is an instance of an OptionParser::Switch
-derived class.
The most important derived classes are:
- OptionParser::Switch::NoArgument
- OptionParser::Switch::RequiredArgument
- OptionParser::Switch::OptionalArgument
These classes are in charge of handling arguments according to their specialization.
It also retains the block passed as an argument of the OptionParser#on
method. This block is stored as an instance of Proc
inside the corresponding switch.
There is a lot of vocabulary to assimilate and this can be hard to unravel.
So, let’s break down this concept by a series of examples for each switch.
OptionParser::Switch::NoArgument
The basic use of OptionParser#on
is to handle an option that doesn’t expect any argument
# in parser.rb
require 'optparse'
require 'optparse/time'OptionParser.new do |parser|
parser.on('-t', '--time') do |time|
p time
end
end.parse!
In the above example, the program will be able to associate the short option -t
and the long option --time
to the block passed as an argument of the parser.on()
method.
In this case, the option won’t require any argument.
So, the generated switch will be an instance of OptionParser::Switch::NoArgument
.
This means that any argument passed to the -t
option will be ignored
?> ruby parser.rb --time=11:12:13
true
Here, the argument 11:12:13
of the option--time
is ignored and true
is returned instead.
Now, let’s see how to require an argument for a given option.
OptionParser::Switch::RequiredArgument
Let’s see the syntax to require an argument
# in parser.rb
require 'optparse'
require 'optparse/time'OptionParser.new do |parser|
parser.on('-t', '--time=TIME') do |time|
p time
end
end.parse!
In this case, the option-t
requires an argument designated by the TIME
word.
So, the generated switch for the option-t
will be an instance of OptionParser::Switch::RequiredArgument
.
?> ruby parser.rb --time=11:12:13
"11:12:13"
?> ruby parser.rb --time
parser.rb:8:in `<main>’: missing argument: --time (OptionParser::MissingArgument)
Here, the argument11:12:13
of the option--time
is passed as an argument of the block which is passed to the parser.on()
method.
Notice that the time
argument is a String
.
Also, an OptionParser::MissingArgument
error is raised if the argument is not provided to the --time
option.
Now, let’s see how to add an optional argument to an option.
OptionParser::Switch::OptionalArgument
Here is the syntax to add an optional argument
# in parser.rb
require 'optparse'
require 'optparse/time'OptionParser.new do |parser|
parser.on('-t', '--time[=TIME]') do |time|
p time
end
end.parse!
The optional argument is designated by the =TIME
word surrounded by square brackets ([=TIME]
).
In this case, the generated switch for the option -t
will be an instance of OptionParser::Switch::OptionalArgument
?> ruby parser.rb --time=11:12:13
"11:12:13"
?> ruby parser.rb --time
nil
Here the argument11:12:13
of the option --time
is passed as an argument of the parser.on()
block.
Also, the time
argument is nil
if no argument is provided to the--time
option.
In our example, time
is a String
. It should be cool to receive this block argument as an instance of Time
.
OptionParser#on and Type Coercion
To do so, we can add a third argument to the OptionParser#on
method. This argument excepts a Ruby class in order to convert the option’s argument to an instance of the given class type
require 'optparse'
require 'optparse/time'OptionParser.new do |parser|
parser.on('-t', '--time=TIME', Time) do |time|
p time.class
end
end.parse!
Let’s run the program
?> ruby parser.rb --time=11:12:13
Time
Here, we can see that the argument time
is now an instance of Time
— as given as the third argument of the parser.on()
method call.
Ruby Mastery
We’re currently finalizing our first online course: Ruby Mastery.
Join the list for an exclusive release alert! 🔔
Also, you can follow us on x.com as we’re very active on this platform. Indeed, we post elaborate code examples every day.
💚