How to Build Your Own Gem in Ruby
As the name implies, the Ruby programming language thrives thanks to the presence of gems. Like the plugins that came before them, gems are mini-pieces of code used to perform specific duties without interfering with or becoming a direct part of our code. The code required for a gem will still be a part of our project’s ecosystem, but we will ultimately remove some overhead –and avoid unnecessary duplication– by using a gem instead of coding it all up on our own.
So why create a gem? Gems are a helpful byproduct created when you either have a piece of code that gets broken out to stand alone or else when a developer realizes this bit of code might actually be helpful to others. If we want to use that code elsewhere or want to share it, that’s when it’s time to make a gem.
A gem is easy to build and more than likely, the tools needed to create them have already been installed in your environment. Our first step is to get bundler installed. Rails is the project where Bundler’s most well-known usage occurs, but we can also use Bundler –not only for gem dependency management– but also for writing our own gems.
$ gem install bundler
Once the bundler is installed, we’re almost ready to start the gem making process. But before actually writing anything or creating a sandbox to work with, we need to do one of the most difficult things in all of programming: naming things.Our gem should have a name that describes what it does, is easy to remember, and hopefully hasn’t been used before. To double check the names of potential gems, check out the search function of Rubygems.org. Additionally, this search might also bring us to a gem with the same functionality we wanted to create in the first place, thus saving us from additional work in the long run.For this blog post, we are going to write a gem called heynow. The function of this gem will be oriented to people who are using our app after hours, pointing out to them what time it is right now. Not very useful, but it’s great for our example as it will be pretty simple and straightforward to create. Let’s get started!
$ bundle gem heynow
We will be prompted to select a testing framework (rspec, minitest, or none). Please select a preferred testing framework or, if it does not appear here, select none. For our purposes we will choose rpec.
Next we will have the opportunity to select if we would like this gem to be released under an MIT license and whether a code of conduct will be attributed to your gem. We recommend both but of course those decisions are up to your team.
Once this is done, a directory called “heynow” is created for us to work in. The directory will look like this:
projects pjhagerty$ cd heynow/
heynow pjhagerty$ ls
CODE_OF_CONDUCT.md LICENSE.txt Rakefile heynow.gemspec spec
Gemfile README.md bin lib
The first thing we need to look at is the gemspec file - heynow.gemspec. This file holds all the metadata about the gem. This includes everything from your name as author to which license you’d like to use. In this case, we’ll add the description and keep the standard MIT license that is auto-generated. Our heynow.gemspec file should look like this:
require_relative 'lib/heynow/version'
Gem::Specification.new do |spec|
spec.name = "heynow"
spec.version = Heynow::VERSION
spec.authors = ["PJ Hagerty"]
spec.email = ["pjhagerty@gmail.com"]
spec.summary = %q{The function of this gem will be oriented to people who are using our app after hours, pointing out to them what time it is right now.}
spec.description = %q{The function of this gem will be oriented to people who are using our app after hours, pointing out to them what time it is right now.}
spec.homepage = "https://github.com/aspleenic/heynow"
spec.license = "MIT"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
# spec.metadata["allowed_push_host"] = "https://github.com/aspleenic/heynow"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
spec.metadata["changelog_uri"] = spec.homepage
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
If there are some lines of code here that you don’t understand right away, not to worry. Most of the gemspec file is built automatically so that we can focus on making useful gems. We take care of the author’s section, email, description, summary, and homepage (only if our gem becomes so popular it needs one), and then let the generated code do the rest.
Once we have that sorted and we have our code committed to our repo of choice, we can take a look at versioning our gem. It’s important that we follow the semantic versioning technique we’ve been taught with the rest of our Ruby code. For more on semantic versioning, please see this article.
Versioning for a gem is kept in the lib directory under the gem name file in a script called version.rb (in our case: lib/heynow/version.rb). It’s a simple module and we need not change it as we are working on the very first version of the gem:
module Heynow
VERSION = "0.1.1"
end
(We can worry about upping the version once we have future iterations of the working gem. For now, we’re good to go with the 0.0.1 version.)Now it’s time to write the code to do what we want our gem to do. The actual executable code will be written in lib/heynow.rb. Initially, it looks like this:
require "heynow/version"
module Heynow
class Error < StandardError; end
# Your code goes here...
end
Someone was kind enough to generate a space to let us know where to put your code and it’s assumed that you know how to code. This post will not cover the writing of the code itself or the importance of testing, but we will move on to the next step of creating a gem, which means releasing it to the world. To see the completed heynow gem, take a look at the heynow repo.
We already have a repo setup for the gem, so it is already publicly available. But we need to put it somewhere else to let people know we are giving it to the world: RubyGems.org. Our first step will be to set up an account, using their handy form. Once you have an account, we can then set up our own credentials:
heynow pjhagerty$ gem build heynow.gemspec
Successfully built RubyGem
Name: heynow
Version: 0.1.1
File: heynow-0.1.1.gem
We can then move our gem to RubyGems by issuing the following command:
heynow $ gem push heynow-0.1.2.gem
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at
https://rubygems.org/sign_up
Email: pj@gmail.com
Password:
Signed in.
Pushing gem to https://rubygems.org...
Successfully registered gem: heynow (0.1.2)
With that command, two things will happen: our git repo will be tagged with the version number and our gem will be made readily accessible through its RubyGems page. With any luck, folks will soon be popping heynow into their Gemfile and bundling a better experience for their end users thanks to your diligent work.
If you are interested in some of the gems that Engine Yard has put out or been a part of in the past, take a look at our open source contributions or else dig into our public github repos.