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 put
s 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.