Command Line Gems and ARGV

In a previous post, we built a simple gem to generate a random title, the Titlegen gem. In it's current state, our gem must be included in a project's Gemfile and called within a program via the line:

Titlegen.generate_title

Which will return something like "The Orange Event", or another clever made-up title.

However, forcing users to interact with our gem only within the context of a Ruby program is limiting. What if someone wants to generate a random title in the command line? It's easy to imagine the utility of gem's that can be run from or interacted with via the command line. In fact, as Ruby programmers, we likely interact with gems in this manner every day when we run rspec from the command line.

In this post, we'll make the Titlegen gem executable from the command line, and we'll allow users to call on the gem by passing in certain options from the command line.

Before we get started, let's refresh our memory as to the structure of this project:

Project Structure

The lib directory contains the titlegen.rb file, which contains the main functionality of our gem. That file requires files in the lib/titlegen subdirectory, notably the dictionary.rb file which contains the Dictionary module.

Now, let's talk about the bin directory.

Creating an Executable Gem

The bin directory contains our executable files. An executable file is any file that contains instructions that a computer's operating system can understand and execute. The first goal of creating a command line gem that we can execute with a simple command like generate title is to create an executable file that we can run with a command like ruby bin/generate-title.

How do you make a file executable?

In order for a Ruby file to be executable, we must include the following line at the tope of the file:

#!/usr/bin/env ruby

This is what's known as a "shebang line". It tells the shell which interpreter to use to execute the remainder of the file.

Using the above setup, you can run your program by typing ruby bin/< your file name > into the command line.

Alternatively, you can execute your program by simply typing ./bin/< your file name > into the command line, since the shebang line at the top of your executable file is already telling the shell to use Ruby to interpret the rest of the file.

Also note that our bin/generate-title file, although it will contain Ruby code, does not have a .rb file extension. This is conventional for executable files.

Building Our Executable

The first question we need to ask ourself is: what is the desired behavior? What do we want to happen when a user executes our gem from the command line? In this case, we want to generate and output a random title to the terminal.

To do so we will the use code that we already wrote in lib/titlegen.rb.

Step 1: Requiring the File

Underneath the shebang line, require the titlegen.rb file:

# bin/generate-title
require_relative '../lib/titlegen.rb'
Step 2: Using Our Code

Our Titlegen class is already defined with a #generate_title method. All we need to do is puts out the return value of that method invocation:

puts Titlegen.generate_title

Now, when we run ruby bin/generate_title from the command line, inside the directory of this project, we will see a brand-new title:

(I would see that movie, btw.)

However, we want anyone who installs our gem to be able to type generate title in their terminal, anywhere, anytime, and see a newly-generated title. We need to add the bin/generate-title file to the gem's executables.

Gemspec Executables

Add the following line to your gemspec:

spec.executables << 'generate-title'

Let's test it out. Run rake install to package and install the gem locally. Now, typing generate-title in our terminal should show something like this:

(I would not see that movie.)

We're almost done. The final step of making our gem executable from the command line is allowing users to type generate-title with some options that get executed.

Executing Gems with Options Using ARGV

Let's say we want user to be able to generate some REALLY LOUD titles, i.e. titles in all caps. They should be able to type generate-title LOUD to achieve this. To take in user-inputted arguments when a gem is invoked from the command line, we used the ARGV constant.

What is ARGV?

ARGV is a constant defined in Ruby's Object class. It is an Array variable that holds, as strings, any arguments passed into the shell when an executable file is executed.

Anytime an executable file is invoked, Ruby will capture any and all command line arguments and store them as strings in the ARGV array. This array does not store the file or program name. ARGV[0] points to the first argument passed to the program.

In our case, ARGV[0] would equal "LOUD", if a user types generate-title LOUD in the terminal.

We can access the ARGV array in our executable file, and operate on it just as if it was any old array.

Coding Our Executable With ARGV

If a user types in generate-title LOUD, we should output an upcased version of the generated title. If they simply type in generate-title, we generate and output a normal title. If they type in generate-title some_nonense we should output a helpful message:

if ARGV[0] == "LOUD"
  puts Titlegen.generate_title.upcase
elsif ARGV[0]  && ARGV[0] != "LOUD"
  puts "please use generate-title or generate-title LOUD to generate a title."
else
  puts Titlegen.generate_title
end

Note that we use ARGV[0] to capture and examine whatever was typed after generate-title in the command line, i.e. whatever arguments our user passes in to their invocation of our executable.

Now, if we rake install, we should be able to use our gem in the following ways:

Great! We're ready to up the version number of our gem and re-release it to the world.

subscribe and never miss a post!

Blog Logo

Sophie DeBenedetto

comments powered by Disqus
comments powered by Disqus