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:
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:
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
Now, let's talk about the
Creating an Executable Gem
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
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:
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
Step 1: Requiring the File
Underneath the shebang line, require the
# bin/generate-title require_relative '../lib/titlegen.rb'
Step 2: Using Our Code
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:
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.
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
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 points to the first argument passed to the program.
In our case,
ARGV 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 == "LOUD" puts Titlegen.generate_title.upcase elsif ARGV && ARGV != "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 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.