Section 6.5. Commands

6.5. Commands

Our first example of using GemPlugins will be to write a new command for Mongrel to make it quack like a duck. Matt has an affinity for quacks, so it seemed appropriate. Mongrel's commands are implemented as GemPlugins so they can be added easily without modifying Mongrel's source directly.

6.5.1. Generate the Project

GemPlugin comes with a command called gpgen, which generates a skeleton project ready for you to use. You run it like you would the rails command to start a project:

$ gpgen duck

This will print out the files being created, most of which you won't have to edit. The important files are:

  • duck/COPYING Your license or copying restrictions.

  • duck/lib Where you store your source for the plugin to use.

  • duck/Rakefile Builds your stuff.

  • duck/resources A place to put files your plugin might need.

  • duck/lib/duck/init.rb Required to initialize your plugin.

  • duck/resources/defaults.yaml Default configuration options.

We'll be skipping the defaults.yaml and resources for now. They let you package additional configuration information with your gem plugin, which GemPlugin will also load. You should refer to the GemPlugin RDoc[12] for more information.

[12] The easiest way to get to any gem's RDoc is to run gem_server and access it with your browser.

6.5.2. Set Up the Project Files

In order to set up our duck command, we need to tweak the Rakefile and put some code in the init.rb, then simply install the gem and go. First the Rakefile needs some lovin':

version="0.1" ... setup_gem(name, version) do |spec|   spec.summary = "The Mongrel Duck Quacker"   spec.description = "What is the sound of a duck typing?" = "Matt Pelletier"   spec.add_dependency('gem_plugin', '>= 0.2')   spec.add_dependency('mongrel', '>=')   spec.files += Dir.glob('resources/*/') end

This will configure the gem task for Rake so that it is properly attributed, has the right dependencies for GemPlugin (both gem_plugin and mongrel), and includes any resources (we have none). Try to build it to make sure at least this much was done.

$ rake $ gem install pkg/quack-0.1.gem

You should see some really boring build stuff and then in the pkg directory is the gem. Install and uninstall it to make sure it works.

If you were serious about distributing this gem you'd also want to update the COPYING and LICENSE files (not sure why this needs both) and add any other dependencies you need.

6.5.3. Write the Initialize File

With our build working, we now just need to toss some code into the init.rb file to get things in motion. This is where we take a slight diversion into "Why the Lucky Stiff" land. Mr. Stiff wrote a really cool article about hijacking contexts. Using this, GemPlugin can have a "second name space" that you register your plugins with outside of the usual Ruby Module system. This is handy for finding plugins by a sane category system without trolling through all the registered classes.

The best way to show you how this works is to just show you the Duck command's code and then explain it:

require 'mongrel' require 'gem_plugin' class Duck < GemPlugin::Plugin '/commands'   include Mongrel::Command::Base     def configure      options [               ['-a', '--annoying LEVEL', 'Just how annoying?', :@annoying, 1],             ]   end     def validate     @annoying = @annoying.to_i     valid?  @annoying > 0, "--annoying must be an integer"     return @valid   end   def run     @annoying.times {|i| puts "QUACK! "}   end end

We start off by simply requiring the libraries we need, and then we declare the Duck class. See that odd syntax in that GemPlugin::Plugin "/commands" bit of code? That's the weird "register this class under /commands" way of making a GemPlugin. Using this class declaration style (which is not standard Ruby in any way), Mongrel is able to ask GemPlugin to give it a list of all classes registered under "/commands" and then run them as needed based on names. It's quite voodoo but it does have a great usage in this case.

The next step is to include the Mongrel::Command::Base module to give your class all the features of a Mongrel command. This hooks up a bunch of extra code, so you should go read the RDoc for this in the Mongrel documentation.[13]

[13] Remember, easiest way is gem_server.

Once we've got this basic setup going we just need to write three functions: configure, validate, and run. They are run in this order and do basically what they say. The contents of configure are almost always setting up options, but you can do other stuff that needs to work before validation.

The validate function then uses a set of handy valid? methods to check for conditions, reports errors and aborts if anything doesn't match. The return value of this function should be @validate (it just should be, don't ask why).

With that all over with, the run command should be set up, have all its settings validated, and should be ready to go. As you can see, we print out a series of annoying "QUACK!" messages in honor of Matt.

6.5.4. Install and Play

This part is very simple; you just need to run rake again and install:

$ rake  $ gem install pkg/quack-0.1.gem

Now when you run mongrel_rails, you should see your fancy duck command, and you can then do:

$ mongrel_rails duck -a 10

Wow, isn't that annoying? Quack, quack, quack all day long.

Mongrel. Serving, Deploying, and Extending Your Ruby Applications
Mongrel. Serving, Deploying, and Extending Your Ruby Applications
ISBN: 9812836357
Year: 2006
Pages: 48 © 2008-2017.
If you may any questions please contact us: