Photo by Kaleb Dortono on Unsplash

Program Arguments in Ruby II: OptionParser

Tech - RubyCademy
RubyCademy
Published in
3 min readJul 12, 2018

--

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 method
  • OptionParser#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! 🔔

🔗 Ruby Mastery by RubyCademy

Also, you can follow us on x.com as we’re very active on this platform. Indeed, we post elaborate code examples every day.

💚

--

--