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

class OptionParser#on method

method OptionParser#on and type coercion

Before to start

I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1

Please feel free to spread the word and share this post! 🙏

Thank you for your time!

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 method

The OptionParser#on method adds a switch associated to 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 specialisation.

It also retains the block passed as argument of the OptionParser#on method. This block is stored as a 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 example for each switch.

OptionParser::Switch::NoArgument

The basic use of the OptionParser#on method 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 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 11:12:13 argument 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 -t option requires an argument designated by the TIME word.

So, the generated switch for the -t option 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 11:12:13 argument of the --time option is passed as 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 -t option 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 11:12:13 argument of the --time option is passed as 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 a Time object.

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 time argument is now an instance of Time — as given as the third argument of the parser.on() method call.

Voilà!

May I have your attention please 🎤🎤

Feel free to subscribe here: www.rubycademy.com