This article is crossposted on Ruby Advent .
!{float:right}http://dominomag.typepad.com/photos/uncategorized/wilkinson_paintborders.jpg(From http://www.dominomag.com/daily/blogs/scrappy/2006/08/)! Coding with Rails (or any other framework) is like doing paint by number. You still can cheat and place different colors in some spots, add your personal touch and paint on top of the lines. But, it’s still painting by number. There’s nothing wrong with this when you’re doing the same thing over and over again. But sometimes you need to start with a blank canvas.
Rack is your Ruby web canvas. It’s the bare minimum you need to build a web app. It can be summarized in one line of code.
proc { |env| [200, { "Content-Type" => "text/html" }, "body"] }
That’s it. A Rack app is an object that respond to call(env)
and returns and array of 3 elements: status code, headers and body.
What, How, Which, When, Who ?
I won’t go through more details of what is Rack, how it works and how to use it. Pratik Naik has written some very good posts about it. You should read them first if you’re not familiar with Rack.
- “Hello Rack!”:http://m.onkey.org/2008/11/17/ruby-on-rack-1
- “The Builder”:http://m.onkey.org/2008/11/18/ruby-on-rack-2-rack-builder
Now that we’re speaking the same language, I’d like to share some cool projects that emerged around the Rack ecosystem.
rack-contrib
rack-contrib by Ryan Tomayko is collection of Rack Middleware and Utilities.
At this time of writing, rack-contrib contains all those middlewares:
Rack::ETag
- Automatically sets the ETag header on all String bodies.Rack::JSONP
- Adds JSON-P support by stripping out the callback param and padding the response with the appropriate callback format.Rack::LighttpdScriptNameFix
- Fixes how lighttpd sets the SCRIPT_NAME and PATH_INFO variables in certain configurations.Rack::Locale
- Detects the client locale using the Accept-Language request header and sets a rack.locale variable in the environment.Rack::MailExceptions
- Rescues exceptions raised from the app and sends a useful email with the exception, stacktrace, and contents of the environment.Rack::PostBodyContentTypeParser
- Adds support for JSON request bodies. The Rack parameter hash is populated by deserializing the JSON data provided in the request body when the Content-Type is application/json.Rack::Profiler
- Uses ruby-prof to measure request time.Rack::Sendfile
- Enables X-Sendfile support for bodies that can be served from file.Rack::TimeZone
- Detects the clients timezone using JavaScript and sets a variable in Rack’s environment with the offset from UTC.
Phew, That’s a lot! Some of this stuff use to be Rails only. But now that it’s a Rack middleware, any framework (that is based on Rack) can use it.
For example, Rack::MailExceptions
can now replace Rails exception_notification and merb_exceptions. So next time you build a framework plugin, think about building a middleware instead and contribute it to Ryan Tomayko’s project.
rack-cache
Another awesome project from Ryan Tomayko, rack-cache is Real HTTP Caching for Ruby Web Apps.
It features a very nice configuration language:
use Rack::Cache do
# set cache related options
set :verbose, true
set :metastore, 'memcached://localhost:11211'
set :entitystore, 'file:/var/cache/rack/body'
# override events / transitions
on :receive do
pass! if request.url =~ %r|/dontcache/|
error! 402 if request.referrer =~ /digg.com/
end
on :miss do
trace 'missed: %s', request.url
end
# bring in other configuration machinery
import 'rack/cache/config/breakers'
import 'mycacheconfig'
end
rack-sandbox
rack-sandbox by … me, allows you to run your Rack app inside _why’s Sandbox. You could, for example, safely run a tryruby clone with this line of code:
run Rack::Sandbox.new("proc { |env| Rack::Response.new(eval(Rack::Request.new(env).params['code'])).finish }")
Metal
metal by Joshua Peek is a plugin for Rails (Edge only atm) that allows you to put your Rack middlewares inside the app/metals directory. Yes, Rails Edge is now running on Rack!
rack-roll
Finally, most useful last, rack-roll by Jeffrey Chupp helps you randomly rick roll your users, they’ll thank you for it.
And … rack
Rack core itself is full of useful middlewares and tools too:
Rack::MethodOverride
- OverrideREQUEST_METHOD
with _method post params for HTML forms.Rack::Head
- Drop the body of the response on HEAD requests.Rack::Deflater
- gzip your responses.Rack::ConditionalGet
- enables conditional GET using If-None-Match and If-Modified-Since.Rack::Session::Cookie
andRack::Session::Memcache
- provide session management.Rack::Auth::Basic
- implements HTTP Basic Authentication.
Learn to love Rack, cause Rack loves you!