Rack est une interface entre votre serveur web et votre application basé sur le standard CGI mais sans ses caractéristiques globales (variables d’environnement et sortie standard).
Dans Rails 2.3
Depuis Rails 2.3, toute application développée autour du framework tourne avec Rack.
L’implémentation de rack est la suivante :
- ActionController::Dispatcher.new est l’application rack de base
- Le parseur de paramètres (ActionController::ParamsParser)est implémenté en tant que middleware
- Le routeur est une application rack qui dispatche vers les contrôleurs
- Chaque contrôleur est une application rack
cela a donc permis d’implémenter la notion de metal, des applications rack tournant autour de Ruby.
Mais ne nous attardons pas sur les choses qui sont vouées à disparaitre et passons plutôt directement à ce qui est intéressant : les nouveautés apportées par l’implémentation de Rack dans Rails 3.
Dans Rails 3
Vous l’avez déjà vu, Rails 3 implémente le concept d’application.
Chaque application est un objet contenant un routeur et des paramètres et configuration … Mais avant tout une application Rack !
Par conséquent les 10 lignes de code suivantes sont une application Rails 3 qui fonctionne.
Dans un fichier nommé config.ru, placez :
require "action_controller/railtie"
class FooController < ActionController::Base
def bar
self.response_body = "Hello World !"
end
end
class MyApp < Rails::Application
config.session_store :disabled
routes.draw do
root :to => "foo#bar"
end
end
run MyApp
Lancez l’application : rackup -p 4000. Rendez-vous sur localhost:4000 et vous verrez un bel « Hello World ».
Vos applications les plus simples n’ont plus rien à envier aux applications Sinatra.
Nous avons vu plus haut que Rails 2.3 commençait déjà à être conçu autour de middlewares rack. Dans cette nouvelle branche, cette intégration est encore plus flagrante.
En effet Rails 3 inclue les fonctionnalités suivantes chacune dans un middleware différent :
- Un middleware exécutant les preparation callbacks
- Un middleware pour lire et écrire les cookies
- Un middleware qui nettoie les flash déjà affichés
- Un middleware qui gère les requêtes HEAD
- Un middleware vérifiant les IP spoofing
- Un middleware servant à rendre les fichiers statiques
- Un middleware de gestion des exceptions de bas niveau
- Un middleware pour les divers stockages en session
- Un middleware pour synchroniser les requêtes non thread-safe Dépends de Rack, pas de rails
- Un middleware pour mesurer le temps d’exécution d’une requête Dépends de Rack, pas de rails
- Un middleware permettant d’implémenter la sémantique de Send-file dans les divers serveurs Dépends de Rack, pas de rails
- Un middleware permettant de détecter les requêtes PUT et DELETE transmises en POST Dépends de Rack, pas de rails
Bien évidemment vous pouvez dans votre application ajouter, réordonner ou supprimer des middlewares.
Le routeur
Le routeur de Rails 3 a également été réécrit afin d’être mieux implémenté dans Rack. C’est Rack::Mount.
Celui-ci reconnait des URL et les dispatche vers n’importe quelle application, même si elles ne sont pas rails. Il est ainsi tout à fait possible de faire la chose suivante
Rails.application.routes.draw do match "/blog" => BlogApplication end
Vous n’avez plus qu’à écrire votre application de blog et elle sera intégrable dans votre application principale sous l’url /blog.
Vous pouvez ainsi beaucoup plus aisément diviser votre application en de multiples modules, rendant chaque brique plus légère et donc plus aisée à développer.
Actions
Comme dit plus haut, chaque contrôleur est lui même une application Rack. Cela va même plus loin que cela puisque chaque action est en elle même une application rack !
Que vous pouvez exécuter indépendamment de l’application rails en elle même.
Cela se fait grâce à
MyController.action :index
Supposons par exemple un contrôleur Posts et une action show que vous souhaitez exécuter.
Le fichier config.ru suivant sera exécuté sans problème avec rack.
class PostsController < ActionController::Base
append_view_path "/path/to/views"
def show
render
end
end
run ArticlesController.action(:show)
Votre rendu et tous vos callbacks seront bien évidemment exécutés.
En fait, en interne, c’est grosso modo ce que rails lui même fait.
Dans les tests
L’utilité de ceci est une plus grande facilité d’exécution des tests.
Dans rails 2.3, si votre application dépends beaucoup de middlewares, ceux-ci seront assez difficile à tester dans vos tests fonctionnels car ils ne seront pas exécutés.
C’est notamment le cas si vous utilisez devise.
La solution trouvée est de mocker les fonctions implémentées par le middleware.
Avec Rack::Test, vous pouvez fortement simplifier cela. Reprenons notre méthode show précédente et testons la.
Tout d’abord en instanciant l’application en elle même.
class TestApplication < Test::Unit::TestCase
include Rack::Test::Methods
def app
MyApplication
end
def test_get
get "/posts/1"
assert_equal "Hello world !", last_response.body
end
end
Et puis comme on peut ne faire que un appel à l’action, on se prive pas
class TestPosts < Test::Unit::TestCase
include Rack::Test::Methods
def app
PostsController.action(:show)
end
def test_get
get "/posts/1"
assert_equal "Hello world !", last_response.body
end
end
Avant de vous amuser à appeler directement une action dans vos tests, demandez vous si c’est vraiment DRY.
In fine
Si Rails 2.3 a commencé l’implémentation de Rack, Rails 3 plonge à plein nez dedans, s’intégrant pleinement avec l’application.
Cela permet de rendre votre application beaucoup plus modulaire et puissante.
Nous avons vu ici une partie des nouvelles fonctionnalités du routeur. Mais ce n’est pas tout à ce niveau ! Attendez vous à d’autres




