gem that - James Adam

How do you build a Ruby gem? It's not that complicated. You write a gemspec that contains something like this:

s.name = "my_gem"
s.version = "1"
s.authors = ["James Adam"]
...

Then you build your gem:

$ gem build my_gem.gemspec

It's really not hard. So, James asks, why do we have so many tools that are intended to make it easier to build a gem? Hmmmm, curious...

The rest of this article is best understood in context. James wants a tool that will make it really easy for him to share some code that he's been working on as a gem. He wants to build a gem and upload it to gemcutter, or rubyforge, or wherever. He doesn't want anything else. At all.

Tools should not get in your way

Sounds fair enough to me. Let's look at the contenders.

hoe -- the godfather of gem creation

It creates a load of files, almost none of which you need. While it's creating these files it prints out messages that tell you what you need to "FIX", with lots of stuff that (unless you know better) you might think you actually do need. If you have a poke around you'll find something that looks a bit like this:

Hoe.spec 'hoe_project' do
  # ???
end

What do you do put in there? You clearly have to learn how to use hoe. Why would you want to do that? You only want to build a fscking gem!

James pointed out that hoe is not unlike a virus; hoe becomes a dependency of any gem that is packaged with it. Your users will need to install hoe. As James put it, "and why wouldn't you want hoe?" Quite.

newgem

newgem is basically a code generator. It can generate loads of stuff. There's a rumour that "it's bat-shit mental" with a myriad of rake tasks (34 of them, to be precise). What do these tasks have to do with packaging a gem? You can do stuff like posting to a blog, or printing a list of email addresses for the authors of the gems that your gem depends on. Do you need that? Yeah? Great, use newgem.

If -- at any point -- you think you might be starting to lose your grip on reality, James pointed out that newgem can help there too...

$ rake -T release_sanity

newgem does, er, lots of stuff

echoe

echoe was intended to be a fork of hoe that doesn't suffer from the viral problem, and that doesn't generate mountains of cruft. You do then have to work out how to use it, and that's not very easy to achieve.

You also need to put this in your Rakefile, so that people who don't have echoe installed can still use your Rakefile:

begin
  require 'echoe'
  Echoe.new('my_gem')
rescue LoadError
end

James clearly considered that to be a rather unnecessary smell, and quickly moved on to the next option.

gemhub

He liked gemhub; it looked cool. It doesn't create many files, and you run it like this:

$ gemhub gemhub_project

It creates spec/gemhub_project_spec.rb and README.textile. It's opinionated. James is clearly slightly opinionated about these things too (and let's be fair, as a developer of a gem, picking your technology is your right), and prefers shoulda and Markdown. Fail. Next.

jeweler

Interesting, and seems to be tailored towards people who use github.

However it's got the begin/rescue LoadError in your Rakefile problem that did it for echoe. You do get a bunch of Rake tasks that appear to complicate your life; it's all just stuff that James doesn't need.

James's solution -- gem this

So why did none of these gem tools take your code and package it up for you, without adding a bunch of irrelevant crud to your project?

It's a good question, and I'm stumped too. To be honest, the complexity of hoe and newgem actually put me off distributing my code as gems (at all) when I first came to Ruby. I was missing the simplicity of Python's distutils and thought "fuck it". This has been a rather tongue in cheek review of the state of gem creation, but the importance of keeping this stuff simple should not be underestimated.

So anyway, back to the talk. James wrote "gem this", which produces just one file; a Rakefile. The Rakefile knows how to build a gem for your project, and how to build your docs (should you have any). That's it; you take responsibility for uploading it to your preferred gem host.

In the Rakefile you'll find a gem specification, along with a link to the docs on how to create gems. You also get a couple of Rake tasks (James hasn't written them; they come with rake) for building your gem and building your docs.

Here's how you use it:

$ cd my-existing-project
$ gem-this

Done.

A very funny talk, on what looks like a cracking little utility. I have to agree, why was life so hard?

Writing gem commands

Whoah, we're not done yet people. While knocking up gem this, James discovered how you can extend Rubygems with extra commands. In other words, you can also run gem-this like so:

$ gem this

How do you do it?

  1. Create a subclass of Gem::Command in a file called rubygems_plugin.rb.
  2. Put it in a directory in the $LOAD_PATH.

Here's an example:

require 'rubygems/command_manager'
require 'rubygems/command'

class TestCommand < Gem::Command
  def initialize
    super 'name', 'short description', { :debug => false }
    add_option('-d', '--debug', 'guess!') do |d, options|
      options[:debug] = d
    end
  end

  def summary
    "String that says what this comand does"
  end

  def execute
    # The code to run your command.
    # It access to the options hash.
  end
end

Gem::CommandManger.instance.register_command :test

James suspects that your class needs to be named SomethingCommand for this to work.

He's @lazyatom on Twitter, and interblah.net on the Internets.

More talks from Ruby Manor