This article is crossposted on Ruby Advent .

!{float:right}! 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!”:
  • “The 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 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.


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 =~ /

  on :miss do
    trace 'missed: %s', request.url

  # bring in other configuration machinery
  import 'rack/cache/config/breakers'
  import 'mycacheconfig'


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"proc { |env|['code'])).finish }")


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!


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 - Override REQUEST_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 and Rack::Session::Memcache - provide session management.
  • Rack::Auth::Basic - implements HTTP Basic Authentication.

Learn to love Rack, cause Rack loves you!