Ruby things worth looking into
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.
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 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.
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 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 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.