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.
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
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?
- Create a subclass of
Gem::Command
in a file calledrubygems_plugin.rb
. - 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
- Browser Level Testing - Martin Kleppmann
- Data Visualisation with Ruby - Chris Lowis
- Denormalising Your Rails Application - Dan Lucraft
- Introduction to Rango - Jakub Šťastný
- Ruby and Cocoa - James Mead
- RubyGoLightly - Eleanor McHugh
- Secrets of the Standard Library - Paul Battley
- Short Order Ruby - Ben Griffiths
- Testing Third Party HTTP APIs - Richard Livsey and Bartosz Blimke
- The Joy of Painting with Ruby - Jason Cale
- Ruby Manor 2008 morning session and afternoon session