Finalist

Finalist Developers Blog

Rack

22 March 2010 18:02 · Iain Hecker · Ruby

Het beste wat de Rubyisten de afgelopen jaren is overkomen is de opkomst van Rack. Met Ruby on Rails 3 in beta fase, is het populairste framework van Ruby helemaal doordrenkt van Rack. Ook is het een jaar geleden dat Ruby on Rails, als laatste van de Ruby frameworks, Rack ondersteuning kreeg. Een goed moment dus om wat dieper te kijken naar Rack.

Wat is Rack?

rack-logo

Rack is het protocol dat bepaalt hoe webservers (zoals Apache, nginx en Mongrel) omgaan met webapplicaties (zoals Ruby on Rails en Sinatra). Omdat Rack de enige standaard is voor Ruby, maakt het de integratie tussen webserver en webapplicatie erg eenvoudig.

Rack is gebaseerd op Python’s WSGI (Web Server Gatway Interface). Vanaf de eerste versie van eind 2007 tot begin 2009 zijn alle webservers en alle webframeworks gaan werken met Rack.

Je kan Rack zien als het absolute minimum van wat een web request inhoudt, uitgedrukt in standaard Ruby objecten, zoals lambda’s, hashes en arrays. Je kan dus ook heel eenvoudig je eigen webapplicatie schrijven, zonder behulp van (de vaak wat zwaardere) frameworks.

Het Rack protocol is zo eenvoudig, dat je een webapplicatie in 1 regel kan schrijven:

lambda { |env| [200, {"Content-Type"=>"text/plain"}, ["Hello World!"]] }

Rack up! en Middleware

Rack applicaties kunnen op elkaar gestapeld worden. Een Rack applicatie kan sessies voor je beheren, de volgende kijkt naar cookies, de andere vangt errors af en toont een mooie error pagina. Deze Rack applicaties heten “middleware”. De laatste Rack applicatie heet het endpoint en is je feitelijke webapplicatie.

Je zal eigenlijk altijd wel wat Rack middleware nodig hebben om een geldige applicatie te kunnen bouwen. Een voorbeeld is bijvoorbeeld Rack::ContentLength. De specificatie vereist dat voor (bijna) alle responses de Content-Type en Content-Length header meegegeven dienen te worden. Content-Type kan je zelf prima invullen (“text/plain”, “application/json”, etc). Content-Length is lastiger en de middleware Rack::ContentLength zal deze automatisch voor je invullen.

Om te specificeren welke middleware je wilt gebruiken, specificeer je een zogeheten “Rack Up!”-file. Standaard noem je deze config.ru en deze staat in de root directory van je project.

De simpelste variant ziet er zo uit:

use Rack::ContentLength
app = lambda { |env| [200, {"Content-Type"=>;"text/plain"}, ["Hello World!"]] }
run app

Er zijn al ruim honderd Rack middlewares. Een overzicht van middlewares vind je hier, hier en hier.

Rails on Rack

Als je met Ruby on Rails ontwikkelt, is Rack niet meteen duidelijk. Toch is er een sloot aan Rack onderdelen die onder de oppervlakte hun werk doen.

In Rails 2 was het nog zo dat je gehele applicatie 1 Rack applicatie was. In Rails 3 is elke controller action die je schrijft een losse Rack applicatie. Dit betekent bijvoorbeeld dat Rails en Sinatra vrolijk door elkaar heen gebruikt kunnen worden.

Een voorbeeld RackUp-file zou kunnen zijn (in het kader van overzichtelijkheid, heb ik het laden van dependencies weggelaten):

class PostsController < ActionController::Base
  def index
    respond_with @posts = Post.where(published: true)
  end
end
 
run PostsController.action(:index)

De router van Rails 3 (echte middleware) is zo verbouwd dat het alleen een sjieke DSL is voor het verwijzen van URL’s naar Rack applicaties. Je kan nu dus zonder probleem Rails en Sinatra door elkaar heen gebruiken.

Conclusie

Rack is geen uniek concept. Het is wel een prima voorbeeld van de innovatiedrift en flexibiliteit van de Ruby community. Door Rack te omarmen en binnen 1 jaar alle frameworks en webservers compatible te maken, laat de community zien dat ze allerminst stil staat.

Rack is ook een prima voorbeeld van de elegantie waarop binnen Ruby over programmeren gedacht wordt. Geen grote complexe specificaties, geen uitgebreide interfaces, maar een kleine en flexibele afspraak. Precies genoeg om de essentie vast te leggen, zonder in vrijheid van implementatie in te hoeven leveren.

1 reactie »

  1. Ik heb er nog nooit zo bij stil gestaan, maar het is wel waar wat je zegt, de adoptie van Rack is absoluut een toonbeeld van hoe de Ruby community kan samenwerken. Mede dankzij Rack is Rails nog volwassener geworden.

    Martijn Storck - June 2, 2010 16:51

Reageer

RSS feed for comments on this post · TrackBack URI