P O S T M O D E R N

Ruby things worth looking into

ffi, gem, gemcutter, handler, libffi, rack, rdoc, ruby, rubygems, sinatra, thor, yard

Over the past couple of months, I've been researching and playing with various up-and-coming Ruby libraries/services. So I thought it would be useful for other developers if I wrote something up.

Sinatra

If you already haven't heard, Sinatra is cool sauce. Sinatra is a Ruby Domain Specific Language for creating web-apps that can fit in a single file.

# myapp.rb
require 'rubygems'
require 'sinatra'
get '/' do
  'Hello world!'
end
$ gem install sinatra
$ ruby myapp.rb

It's that easy. But let's say you want to create an app accessible as a Class, just inherit Sinatra::Base.

require 'rubygems'
require 'sinatra'

class MyApp < Sinatra::Base

  get '/' do
    'Hello world!'
  end

end

I found the URL param parsing and request routing on-par with that of Merb/Rails. I also enjoyed the halt and pass methods, which will cause Sinatra to re-route a request to other handlers.

Defining helper methods which can be used within request handlers was as easy as creating a module with some instance methods, then registering the module using the helpers method.

module Helpers
  module Rendering
    include Rack::Utils

    alias h escape_html
  end
end

class MyApp < Sinatra::Base

  helpers Helpers::Rendering

end

Sinatra is built on top of Rack, so reviewing the Rack API might not hurt. The current Rack::Request object can be accessed via the request method. The return value of a request handler can be a String, Array of Strings or even a Rack::Response object. Sinatra also provides the Rack call method, which can be overridden for more custom request routing (such as vhost routing to other Rack apps). Given Sinatra's API Documentation, it's fairly easy to customize and extend your Sinatra app.

Thor

Thor is an alternative to Rake or Sake. Thor makes it very easy to define tasks as methods, and define command-line options/arguments for those tasks using a succinct syntax.

Thor tasks can be invoked via the thor command, or loading the Thor class and calling the start method directly.

I also noticed that Rails3 is using Thor::Group and Thor::Actions, to create code generators.

While documentation is scarce for Thor, I fould it's code-base fairly readable.

FFI

There's an easier way to write Ruby extensions to C libraries. It's called FFI, or Foreign Function Interface. Ruby FFI is a rubygem (named ffi) by Wayne Meissner which wraps around libffi, to provide a Ruby interface to load libraries, attach functions, variables and mapping in Structs/Unions/enums/callbacks.

To create a Ruby interface to a library, simply create a module which extends FFI::Library and attach some functions as module methods.

module FFI
  module TRE
    extend FFI::Library

    ffi_lib 'tre' # finds and loads the library

    # attaches a function named tre_regcomp, and defines the
    # types for it's arguments and return value.
    attach_function :tre_regcomp, [:pointer, :pointer, :int], :int
    # ...
  end
end

More examples can be found here.

If you need to quickly write bindings for a library, give FFI a shot. Another benefit of having FFI Ruby bindings, is that they will work seamlessly with JRuby and Rubinius, on any platform that is supported by libffi.

YARD

YARD is an alternative to the defacto RDoc documentation generation, that allows one to annotate code using a @tag based syntax and Markdown/Textile/RDoc formatting. YARD stores all the gathered documentation information in a Marshalable data-store file (.yardoc), which opens the door to on-the-fly documentation searching. YARD can also export it's data to XML or XHTML+CSS+jQuery.

Want to use YARD in your project? Drop this task into your Rakefile.

YARD::Rake::YardocTask.new do |t|
  t.files   = ['lib/**/*.rb']
  t.options = [
    '--protected',
    '--files', 'History.txt',
    '--title', 'MyProject'
  ]
end

task :docs => :yardoc
$ rake docs && firefox doc/index.html

Want to use YARD on someone else's (github) project, checkout rdoc.info, it's built on YARD and Ruby 1.8.7.

YARD can also be extended to detect and document meta-programming methods which define other methods at runtime. For example, this YARD handler (for Ruby 1.9.x) which documents parameter method-calls from the Parameters library.

Loren Segal's slides from his YARD presentation at Montreal.rb are also worth checking out.

Gemcutter

Gemcutter provides easy and fun RubyGem hosting, which is open-source and aims to become the the default gem hosting solution for Ruby. Did I mention that it looks classy (thanks to a redesign by ThoughtBot)?

Publishing gems to Gemcutter is as easy as running:

gem push pkg/my_project-0.1.0.gem

The gem push command can override previously uploaded versions of a gem. No more going into Rubyforge's File Admin panel to delete mistakenly uploaded versions, just run gem push again.

Also, Gemcutter is a Sinatra app running on Heruko.