The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Building DRY Gems With Thor And Jeweler

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Gabriel Horner

Posts: 62
Nickname: cldwaker
Registered: Feb, 2009

Gabriel Horner is an independent consultant who can't get enough of Ruby
Building DRY Gems With Thor And Jeweler Posted: Apr 9, 2009 2:33 PM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Gabriel Horner.
Original Post: Building DRY Gems With Thor And Jeweler
Feed Title: Tagaholic
Feed URL: http://feeds2.feedburner.com/tagaholic
Feed Description: My ruby/rails/knowledge management thoughts
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Gabriel Horner
Latest Posts From Tagaholic

Advertisement

Being DRY is a concept I try to embrace as a programmer. Lately when creating new gems, I’ve noticed that I copy, paste and tweak the same boilerplate gemspecs/Rakefiles. Fed up with this non-DRY gem configuration, I came up with a gemspec config file solution. With this yaml config file and some thor tasks, I’m able to generate gem specifications for any of my gems.

Before going any further, let me disclaim that while this post uses thor and jeweler, they could be replaced with similar gems i.e sake for thor and any gem creator that takes Gem::Specification objects for jeweler. Having said that, the idea of a gemspec config file is solely dependent on my GemspecBuilder class. If there’s interest from others I can package it up as gem.

Rant

If you’ve been using jeweler like I have, you start each new gem by copying your boilerplate Rakefile which contains a special section for your jeweler config. Taken from the jeweler readme, a Rakefile can as easy as:

  begin
require 'jeweler'
Jeweler::Tasks.new do |gemspec|
gemspec.name = "the-perfect-gem"
gemspec.summary = "TODO"
gemspec.email = "josh@technicalpickles.com"
gemspec.homepage = "http://github.com/technicalpickles/the-perfect-gem"
gemspec.description = "TODO"
gemspec.authors = ["Josh Nichols"]
end
rescue LoadError
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
end

While this is easy, it’s not DRY once you start copying and pasting Rakefiles across your gems. Sure, your name and email are unlikely to change. But what if you want to have other default gemspec attributes such as files, has_rdoc and extra_rdoc_files? And if you want to change some of your default attributes later? What if you’d like to reuse some of the information in your gem specifications to create a gem’s web page? Do you feel yet that maybe you should’ve had a more DRY setup? So instead of having copy and paste configurations spread across my gems, I have one configuration file for them. Since this config file has one section for common gemspec attributes, gemspec management becomes easy and DRY.

How It Works

Using the gemspec config file and a given or detected gem name, GemspecBuilder.build creates a Gem::Specification object. Jeweler’s task class uses this object to create a Jeweler object. To run a jeweler task, I invoke thor to delegate the correct task to the Jeweler object. My thor tasks look like this:

  # cd into one of my gems
  bash> cd hirb
  
  # equivalent to jeweler's rake version
  bash> thor jeweler:version
  Current version: 0.1.2
  
  # equivalent to jeweler's rake gemspec
  bash> thor jeweler:gemspec
  hirb.gemspec is valid.
  Generated: hirb.gemspec
  
  # equivalent to jeweler's rake build
  bash> thor jeweler:build
  Successfully built RubyGem
  Name: hirb
  Version: 0.1.2
  File: hirb-0.1.2.gem
  
  # equivalent to jeweler's rake version:bump:patch
  bash> thor jeweler:bump patch
  Current version: 0.1.2
  Updated version: 0.1.3  

If you aren’t familiar with thor, you may be wondering why I didn’t just stop with making the above Rakefile leaner:

  begin
require 'jeweler'
require 'gemspec_builder' #if it were packaged as a gem
Jeweler::Tasks.new(GemspecBuilder.build)
rescue LoadError
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
end

What thor provides that rake and sake can’t provide is letting you write your tasks as Ruby. This is quite powerful when you want pass arguments and options to your tasks (and testing tasks and sharing task libraries, etc…). Also, thor like sake, allows you to install your ruby tasks to be invoked from anywhere. This allows me to use my jeweler tasks without putting any jeweler (gem creator specific) tasks in my gem’s Rakefile. I think this is a good thing since I leave potential forkers of my gem with a choice of what gem creator they want to use for recreating my gemspec. In the same vein, I forgot to mention that one gemspec config file gives you the painless choice of switching gem creators when the need arises.

Install

If you’re using jeweler as your gem creator, you can give this idea a try:

  1. sudo gem install thor
  2. git clone git://github.com/cldwalker/thor-tasks.git
  3. cd thor-tasks
  4. thor install jeweler.thor
  5. Create a ~/.gems.yml. GemspecBuilder contains documentation about what the config file should look like. Use mine as an example.
  6. Try adding one of your jeweler gemspecs to ~/.gems.yml. Should be copy and pasting for the most part.
  7. cd your_gem_path
  8. Execute your jeweler tasks as demonstrated above. thor list jeweler to list your jeweler tasks.

A few additional notes:

Read: Building DRY Gems With Thor And Jeweler

Topic: Using the vim tag list plugin Previous Topic   Next Topic Topic: BlueCloth 2 Released

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use