It’s raining gems! - How to build your own Ruby gem
If you’ve had a bit of experience in the Ruby programming language, you know the importance of gems in your work. 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 your code. The code required for a gem is still part of your project’s ecosystem, but you’ve removed some overhead (and duplication) by using the gem instead of coding it up yourself.
So what happens when you have a piece of code that might be broken out to stand alone? What if that code might actually be helpful to others? It’s time to build a gem.
Getting started is easy and will use tools you already have installed in your environment, most likely. Your first step is to get bundler installed.
$ gem install bundler
Once bundler is installed, we are ready to start the gem making process. 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 check on names of gems, check out the search function of Rubygems.org - this may also bring you to a gem with the same functionality and save you some work in the long run.
For our example we are going to write a gem called sleepr - it will be used to point out when people using our app are doing so after hours and should just go to sleep. Not very useful, but great for our example as it will be pretty simple. Let’s get started!
$ bundle gem sleepr
This will create a directory called “sleepr” for us to work in. The directory will look like this:
sleepr$ ls
Gemfile LICENSE README.md Rakefile lib sleepr.gemspec
The first thing we need to look at is the gemspec file - sleepr.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 our case, we’ll add the description and keep the standard MIT license that is auto generated. Our sleepr.gemspec
file should look like this:
# -*- encoding: utf-8 -*-
require File.expand_path('../lib/sleepr/version', __FILE__)
Gem::Specification.new do |gem|
gem.authors = ["PJ Hagerty"]
gem.email = ["[email protected]"]
gem.description = %q{Used to point out when people using our app are doing so after hours and should just go to sleep}
gem.summary = %q{A warning so people will logoff and go to bed!}
gem.homepage = ""
gem.files = `git ls-files`.split($\)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.name = "sleepr"
gem.require_paths = ["lib"]
gem.version = Sleepr::VERSION
end
If there are some things here you don’t understand right away, that’s okay. Most of the gemspec file is built automatically so we can focus on making useful gems. We take care of the authors section, the email, description, and summary (and homepage once our gem is so popular it needs one), and 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 is 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/sleepr/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 Sleepr
VERSION = "0.0.1"
end
We can worry about upping the version once we have future iterations of the working gem. For now, we are good with the 0.0.1 version.
Now comes the time to write the code to do what we want our gem to do. The actual executable code will be written in lib/sleepr.rb. It looks like this initially:
require "sleepr/version"
module Sleepr
# Your code goes here…
end
Someone was kind enough to generate a space to let us know where to put our code. We will now take an assumptive leap and say you are aware of how to write some 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, releasing it to the world. To see the completed sleepr gem, take a look at the sleepr 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. Luckily, someone gave us just such a place: RubyGems.org. Our first step will be to setup an account for ourselves using their handy form. Once you have an account, set up on your machine your credentials:
sleepr$ gem push
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at https://rubygems.org/sign_up
Email:
Password:
Next, move your gem to RubyGems by issuing the following command:
sleepr$ bundle exec rake release
At this point, two things will happen: your git repo will be tagged with the version number and your gem will be accessible through its RubyGems page.
The world can rest easy (and at a reasonable time) thanks to our gem. With any luck, folks will be popping sleepr into their Gemfile and bundling a better experience for their end users thanks to our work.
If you are interested in some of the gems Engine Yard has put out or been a part of in the past, take a look at our open source contributions and dig into our public github repos.
Share your thoughts with @engineyard on Twitter
OR
Talk about it on reddit