I’ve been writing a fair few Ruby applications recently, including BetterBankStatement, and a bugzilla poster. Previously I’ve been pointing people to the relevant code repositories and giving them a list of dependencies to install. This hasn’t been ideal.

Many of my colleagues use Ubuntu, and I did investigate into creating a Debian package for my code. I found however that this wasn’t as easy as I’d hoped. It also wouldn’t be much use for my colleagues still using Windows XP. :-D

Using Jeweler it is relatively simple to package up a Ruby code as a Gem. Within a Rakefile (essentially a Makefile written in Ruby) you specify a JewlerTask which provides a block with a gemspec object.

The gemspec object contains the meta information about your Ruby code. Some of this information is required, some of it is optional. Jeweler performs some basic validation on your gemspec. It won’t, for example, allow you to have an empty description - or have a description which is the same as the summary.

The gemspec will package up anything within the lib folder of your application. Once installed these will be placed in the RubyGems path. Any other Ruby application can re-use the code in this folder by including both rubygems and the file required. The gem will also place anything in the bin folder within the runtime path of the operating system. Making any Ruby script in the bin folder accessible from any command prompt. Marvelous.

Here’s an extract from my Rakefile:

begin
  require 'jeweler'
  Jeweler::Tasks.new do |gem|
    # Define the name of the gem
    gem.name = "my-marvelous-gem"
    gem.summary = %Q{A Gem which is marvelous.}
    gem.description = %Q{Solves all the problems of the universe with several neat scripts.}
    # Contact information for the author
    gem.email = "my.email.address@domain.com"
    gem.homepage = "http://www.owengriffin.com/"
    gem.authors = ["Owen Griffin"]
    # Runtime dependencies
    gem.add_dependency "mechanize", "<= 0.9.3"
    gem.add_dependency "markaby", "<= 0.5"
    gem.add_dependency "hpricot", "<= 0.8.1"
    gem.add_dependency "json", "<= 1.2.0"
    # Dependencies required for development
    gem.add_development_dependency "less", "<= 1.2.19"
    # Any other files related to the application
    gem.files << ["filters.yaml", "style.css", "open-flash-chart.swf"]
  end
  Jeweler::GemcutterTasks.new
  rescue LoadError
    puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end

Once the Rakefile is complete you can build them Gem. This is done using the build command. <pre class="brush: shell">rake build</pre> The first time this command is run, you will encounter an error. Jewler is crafty - along with packaging your Gems it contains some helpful scripts for maintaining versions. To initially set the version run the following command: <pre class="brush: shell">rake version:write</pre> This will set the version of your project to be 0.0.0 - this data is held with the VERSION file. To increment the version run the version:bump Rake task. <pre class="brush: shell">rake version:bump:patch # 1.5.1 -> 1.5.2 rake version:bump:minor # 1.5.1 -> 1.6.0 rake version:bump:major # 1.5.1 -> 2.0.0</pre> The Rake build command should now work, and some wonderful gems should appear in the pkg/ folder.

To install the Gems you have created there is another task, but you may need sudo privileges: <pre class="brush: shell">rake install</pre> That’s not all, there’s more! Using the jeweler command you can create the perfect Gem for your new projects. It will create a dummy Rakefile, the correct directory structure and the tasks required for your unit tests.

There’s also some tasks for deploying to Gemcutter and Rubyforge, but I’ve not got that far yet. :-)

References