Gems. Gotta love em. If you’re a Ruby developer then you already know that gems
are simply fundamental to Ruby programming. Let’s write one. Right now. And not
a simplistic Gem that just adds three lines of code to the automatically
generated Gem layout from
bundle gem. Let’s write a real Gem that includes
files and everything.
1. Create a fresh gemset
First off, we need a clean space to work in. So let’s create a brand new gemset in RVM.
# periodic_table will be the name of our gem rvm --create use 1.9.3@periodic_table
2. Install bundler to manage building the gem
There are two applications I know of to help us build a gem: Bundler and Jeweler. I’m familiar with Bundler so we’ll go with that. We just need to install its gem to get going.
gem install bundler
3. Create the initial gem layout
Head to some code storage directory. A lot of folks like a
~/projects. Myself, I keep almost everything on github so I have
~/github/ORG/repos. The ORG lets me group my repos by area of interest:
personal, work, DuckDuckGo, etc.
bundle gem periodic_table
This command takes care of quite a bit.
- creates the directory and initial structure of the gem
- initializes a git repository for the gem
- writes an initial gemspec
- sets up some really helpful rake tasks for development
4. Modify periodic_table.gemspec
Now we’ve got a working gem (seriously), it just doesn’t do anything.
The next step in our gem journey is to give some attention to the gem’s metadata. All of the gem’s information is stored in the gemspec.
The gemspec contains:
- the name of the gem
- the files that are in it
- the gems it depends on for testing
- the gems it depends on for actually running
- lots more
Let’s take a couple minutes and go through an annotated gemspec, then take a move to a modified version ready to commit to the git repo.
Two areas that really confused me when I was starting to learn how to write gems
require "periodic_table/version" and the
s.files. I incorrectly
thought after taking my first look through the gemspec that I would need to add
require statements as I developed my gem. That isn’t the case: the files
just need to be in git.
I’ll say that again. As you develop gems, the (out of the box) requirement that
all files necessary for building the gem be in git can surprise you. While
developing if your gem starts throwing unexpected
LoadError: cannot load such
file errors then check and make sure that you’ve staged any new files in git.
Until you do that the gem will install without issue but will bomb when you
actually try to require it.
Here’s our gemspec ready for a first commit into the repo. All we’ve modified is the summary and description.
5. Make an initial commit to the git repo
git add periodic_table.gemspec git commit -a -m "initial commit"
6. Setup an .rvmrc for the directory
Before we go any further, we should setup an .rvmrc file for the project so RVM will automatically switch to the correct gemset.
rvm --rvmrc 1.9.3@periodic_table git add .rvmrc git commit -m "rvmrc" cd .. cd - # and accept the .rvmrc authorization
7. Install the gem
Sure our gem doesn’t actually do anything yet, but that doesn’t mean we can’t install it. Bundler has provided us with some handy rake tasks to make installing our in-development gem easy.
Bam! Gem installed. Don’t believe it?
% gem list *** LOCAL GEMS *** bundler (1.0.22) periodic_table (0.0.1) % irb 1.9.3p0 :001 > require 'periodic_table' => true 1.9.3p0 :002 > PeriodicTable::VERSION => "0.0.1"
Yeah! Our gem has a namespace and a VERSION! WOO!
Now, be aware that our installed version of the gem has been compiled. If we change the source then we’ll have to uninstall/reinstall the gem to see the change.
gem uninstall periodic_table rake install
8. Write a README
First things first. Let’s write a quick README to figure out how we want this gem to be used.
``` bash README.md
gem install periodic_table
require 'periodic_table' # Lookup data for an element by name PeriodicTable.lookup 'oxygen' ```
There. README driven development at its finest. That’s enough to get going, and certainly enough to keep this tutorial on track.
Continue on to Part 2, in which we actually write the gem and use it in other projects.
Check out the “Let’s Write a Gem” Reddit discussion.