After all, a successful gem makes a Ruby programmer’s life easier

Jordan Moore
Sep 24 · 10 min read

Exploring the simple beauty of the Ruby language, it’s difficult to think of improvements that could be made to make programmers’ lives easier. However, this happens more than you may think, and these improvements often are shared with others in the form of Ruby gems.

A gem is a packaged library or application that can be installed with a tool known as RubyGems. So long as one’s Ruby version is at least 1.9, RubyGems has already been installed alongside the Ruby installation.

Some of the most helpful gems are Bundler, Rake, and Minitest, each with millions of downloads and just as many happy users. The hallmark of a gem is its ability to make a Ruby programmer’s life easier; if an idea has the capacity to do just that, it should be shared with the rest of the Ruby community.

For those readers who have an idea but aren’t sure where to begin, this article is for you.

Creating the Gem

First, locate the directory where the gem will be stored. When deciding where to store it, keep in mind that it is a wise idea to initialize the directory as a Git repository.

On my computer, I’ll store the directory in my Documents folder and name it hello_gem.

Next, navigate inside of the hello_gem directory and create a file named hello.gemspec. Don’t worry — this file will be examined and explained shortly.

Create another directory named lib and inside of that directory create a file named hello.rb. This is the first key part to understanding the structure of a gem: the lib directory is where the code for one’s package is stored. Popular convention is to have only one Ruby file with the same name as the gem. This one file is also in charge of your gem’s code and API.

Here is a picture of my directories for double-checking purposes:

hello_gem directory
lib directory

For the purposes of this guide, the code in this Ruby gem will be simple. Some of the concepts regarding file pathing will get complicated, so it’s sound to keep as much of the code as simple as possible to compensate for this.

Open the hello.rb file and create a Hello class. This class will have one class method for now, greeting, and this method will invoke the puts method with “Hello world!” as its argument.

Hello class!

The code is simple but it’s enough for checking that the gem is functional.

Navigate back to the root of our directory and open hello.gemspec.

The gemspec stores an immense amount of data. The author, the version, the included files, and even more is defined within it. Gem is a Ruby class, and Specification is the class which contains the information for a specific gem.

Edit hello.gemspec to match the gist below, albeit with the correct information for the authors, email, homepage, and date instance variables. The homepage can also be a GitHub link for those who have already initialized this project as a Git repository.

The name instance method has the string “hello_2019_unique” assigned to it. Change the unique portion of the string to something unique so that it doesn’t share the same name as another gem, as this will cause push issues.

What a gemspec!

Let’s build and install the Hello gem. Run the following command in the command line: gem build hello.gemspec

Readers will see the following messages following a successful build:

The Hello gem is built.

After building, it’s time to install the gem. Run the following command:

gem install hello_2019_unique-0.0.0.gem

Hopefully, readers will see the following message:

Successfully installed.

The gauntlet is almost over; let’s require the Hello gem in irb and see if it works. The following picture contains the console output that one should see at this point of the article.

Now we’re cooking with oil!

Next, we’re going to require more files, examine the files instance variable closely, and play with file pathing.

Requiring More Files

Obviously, your gem should include more than just the ability to say “Hello.” To create and include more files, a new directory matching the name of the Ruby file in the lib directory must be created inside of the lib directory. Navigate to the lib directory and do that.

The hello directory is inside of lib.

This is another convention of RubyGems: the additional files used for the gem are located in a directory matching the name of the Ruby file inside of lib. Navigate into the hello directory and create a file named goodbye.rb.

The following gist contains the code one should implement within their Goodbye class.

Next, require goodbye.rb in hello.rb.

Now hello.rb can access the Goodbye class.

Remember how to include more files in the gemspec? Take a look at the gist again and notice what data structure the files are stored in.

The files instance method cannot be appended to; rather, an array must be assigned to it. Additionally, do not bother including directories in this list, as directories are automatically stripped from the gem during the build process.

Most gems are far larger and more complex than this example. Imagine a gem with over 50 Ruby files dispersed among nested directories. How would we assign all of these files without writing all of them by hand?

The Dir[] class method is one of the best answers. With the Dir[] class method, one can use file patterns to match and include the desired files of lib and all of its nested directories. The return value of Dir[] is an array, which is perfect since we need to assign an array to files. Read more on Dir[] before we use it.

Let’s look at some file matching patterns.

According to the previous link, * matches any file. If we include a file extension after the *, like .rb, the pattern now matches all files that end with .rb. This pattern will be used to match and collect our desired files.

The ** pattern is also crucial in assigning the correct files to files. This pattern matches directories recursively and files expansively, which means that if used correctly, we can search all nested directories of lib for the files we wish to include in the gem.

To test out the recursive aspect of **, navigate to the hello directory inside of lib and create a new directory named third_layer. Inside of the third_layer directory, create a file named example.rb. No need to include any code in this file as it is only for demonstration purposes.

This is in the hello directory inside of lib.

Open hello.gemspec again. Navigate to the last line and enter down to a new line. Let’s test out Dir[ with a p method invocation. Try to output all of the files that we want to include from lib. If any readers wish to try using Dir[] on their own, don’t scroll down as the next paragraph and picture contain the solution for including all files from lib.

This is the output of what’s included in files after Dir[].
Readers can test this with the `p` method invocation.

As this example shows, Dir[] is an extremely useful class method. To test this Dir[] method more, create a file with the .txt extension and include it in the files alongside the .rb files. There are a few different ways to do this, even with Dir[]. Try to be as specific as possible!

Now that all of the correct files are included, it’s time to test out hello.rb. Go to the command line and fire up the following line: irb -Ilib -rhello

A little explanation is in order. -I is an option that specifies the $LOAD_PATH directory. In this case, it’s using lib as the $LOAD_PATH directory. The -r option is running the file hello.rb and requiring the gem in the current irb session. There are many more options one can use to modify an irb session, check out the IRB module documentation if interested.

The output of the command line should look like the following picture.

One can invoke the methods from Hello in irb now.

If any readers want to build and install this updated version, be sure to update version in the gemspec.

Version number 0.0.1!

Separating code into distinct files and adding logically ordered directories is integral to creating a gem whose code makes sense to an outsider. Additionally, understanding the pathing in your application helps in crafting well-designed, comprehensive tests.

Adding Executables

Similarly to how we keep writing irb in the command line and executing that program, we can include an executable file in our gem and run the gem with a single command. Gems do this by revealing one or more executable files to the PATH of one’s shell.

To do this, navigate to hello_gem. Then, issue the following three commands:

These commands create the bin directory and our executable file.

These three commands do the following: create the directory bin, which houses executable files. Then, the second command creates the file hello in bin. Last, chmod stands for change mode, which in this case, changes the operation of the file to execute with the +x modifier.

Next, open hello in a text editor. To make this executable actually work, we need to add a shebang to the top of it which will indicate the beginning of an executable shell script in a specific language. Ensure that hello matches the following code.

This is the code for hello in the bin directory.

Close hello and open up the command line again. We’re going to test the executable before we require it in the gemspec. Run the following command in your command line:ruby -Ilib ./bin/hello

Alternatively, one can run the command without -Ilib: ruby ./bin/hello

Since the name of the executable is hello, the executable is executed by calling that same name. After the test has been successfully run, it’s time to include the executable in hello.gemspec. The executables array should be appended onto, in stark contrast to the files array, which should be assigned to.

Updated gemspec for executable hello.

If any readers wish to build and install the new gem, don’t forget to again change the version number. After the installation of the new gem, don’t forget to test it out by typing hello into the command line. How cool is it that we can call our program with one word?

Hello world!

Pushing the Gem to RubyGems

Once the gem is in a usable state for others, you can push the gem to RubyGems for others to download.

First, create a RubyGems account with this caveat: this sounds crazy, but try not to include special characters like $, %, or ! in the password. RubyGems has trouble authenticating a password that uses these characters on the command line, so it’s easier just to not use them in the first place. There are other ways to have a secure password, like varying upper and lower case letters, misspelling words, and more.

Next, run the following command in the command line.

curl -u your_username > ~/.gem/credentials; chmod 0600 ~/.gem/credentials

This command downloads a specific API key for an account. The computer invoking the command is then associated with that specific account. In place of your_username should be the reader’s username.

Once the API is setup, push the gem to RubyGems with this command:

gem push hello-0.0.your_version.gem

And that’s it! The hello gem is now available for download by anyone who uses RubyGems.

Wrapping Up

The goal of this article was to remove as many of the common roadblocks to creating your first gem as possible. There are many more essential practices inherent to making a solid gem, like TDD, using a Rakefile for task automation, and more. These are larger concepts that cannot be covered in a single article.

One of the best ways to learn how to create something is to reverse engineer it. In this case, you can read through a gem’s files, classes, and methods, to glean an absolute understanding of the logic and code that goes into making a gem. Furthermore, one can actually rewrite and refactor the code.

To this end, I suggest starting by reverse engineering a simple application, and not one like Bundler or Rubocop. I recently created a gem named EasyPortfolio, which creates a Sinatra-powered portfolio page for software engineer job applicants. This gem is simple enough to understand for a first-time gem creator but also complex enough to see the power that a gem can wield.

In conclusion, remember the hallmark of a successful gem: the ability to make a Ruby programmer’s life easier. Good luck and Godspeed, Ruby soldiers. Create something beautiful!

Better Programming

Advice for programmers.

Jordan Moore

Written by

Full Stack Developer | Ruby & Javascript Enthusiast

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade