Today we will explore Rack. Rack is a Ruby library that sits between your web app and your HTTP server of choice. Essentially it provides a range of conveniences for interacting with and responding to web requests.
First things first, get yourself the libraries we will be playing with:
Fire up pry, and take a quick peek at Rack:
Remember, Rack sits between the server and your app. Let’s ‘pry’ open the server and take a look:
The docs here give us a valid way to run Rack, nice! Though I hope I am not the only one who finds lamdbas awkward. A dip into the official documentation, or any Rack tutorial, will tell you that a typical Rack app is essentially this:
Which, when visiting ‘localhost’, at the port written in your console, should display ‘Hello World!’ in your browser.
The Rack specification says that a Rack compliant app is an object that has the method ‘call’, which accepts one argument, and returns an Array with three entries: the http status, a hash of http headers and an enumerable with the content you want displayed in the browser.
Let’s keep digging. Break out the above code into a file and drop a ‘pry.binding’ inside the call method.
Running this and visiting the web page will allow us to inspect Rack in action!
What we discover is an array of values that will be familiar to anyone who has played with web frameworks or servers, plus a few additions from Rack itself.
Here on out we will see how Rack really begins to shine as an excellent foundation for web frameworks like Sinatra and Rails.
Our first interactive Rack application! Go to the browser and try adding a name query parameter to the url, like: /?name=LumpySpacePrincess and watch the name in your browser change.
There is one final feature of Rack I would like to cover - Middleware. The secret sauce of Rack. What if I told you we can write discrete, little Rack apps and stack them up as veritable programming lego.
Naturally, rack provides a convenience for this:
If you drop ‘binding.pry’ into ‘Middleman’ you will discover that the middleware is called twice, here’s why:
Middleware is a stack that is first traversed down, then up. The middleware thus has the chance to filter the request twice.
The best part of all. Middleware are extremely reusable. Write middleware for one app, you can probably use it for your next one - and the Rack devs, and the community, have written many many more for us to drop in as we please.
It is my hope with this little Rackventure that you will come away a bit more enlightened about the magic of Rack as the underpinning of popular Ruby web frameworks. You should also have a taste of how easy it is to write your own middleware and with a little reading you will be able to see how your own middleware can be plugged into your framework of choice easily. I also hope you will begin to see how one could begin planning to build a web framework on top of Rack by embracing middleware.
I feel there is a lot of power here and few (1,2) discoveries are lending weight to this notion. As I consume Sinatra and Rails more I will be eagerly looking for opportunities to leverage middleware in my architecture.
Until next time.