mardi 20 décembre 2011

Rails 3.* : Routes avec un param automatique

En travaillant sur les urls d'une application Rails 3 et particulièrement sur les namespaces, j'avais besoin du côté de mes controllers d'un paramètre à exploiter.

Cependant ce paramètre devait être complètement transparent tant pour les controllers que les vues de l'application. En fait il devrait dépendre complètement de mes urls.

Ruby on Rails, en tant que framework nous offre de nombreux moyen.

Pour cet article, nous travaillerons exclusivement dans le fichier config/routes.rb

Prenons comme exemple le cas d'une application pour gérer mon magasin de vente d'articles divers.
Aussi, il me faut une interface pour gérer les stocks et une autre pour les commercialiser.

Donc dans mon application, je vais avoir de la sorte deux 'namespaces' : Stock et Vente qui se traduiront au niveau des url par /stock/articles et /vente/articles

Pour cela nous allons utilisé les namespaces ou scopes dans le routage de Rails :

namespace :stock do
resources :articles
end

namespace :vente do
resources :articles
end
Le problème de cette solution est que dans mes controllers, je ne sais pas aisément dans quel namespace je suis à moins de parser mon url.
D'autre part ce n'est pas très DRY.

Pour savoir systématiquement et aisément dans quel namespace je me trouve, 'stock' ou 'vente', le mieux est d'utiliser le hash params, bien connu quand on traite des données transmises par formulaire.

Nous utiliserons donc params[:namespace] que l'on retrouvera à chaque fois que nous aurons une url de la forme /stock/articles ou /vente/articles. Celui-ci aura la valeur 'stock' ou 'vente'. Rails offre deux possibilités. Celle que l'on trouve dans tous les guides utilise le scope :
scope ":namespace", :module => 'stock', :as => 'stock' do
resources :articles
end
Ainsi à chaque fois que l'on appelera l'url /stock/articles, on aura un params[:stock]='stock'. Les options :module et :as permettent d'avoir le même comportement qu'un namespace. Avec :module il ira chercher le controllers dans app/controllers/stock/articles_controller.rb. Et avec :as il créera les helpers stock_articles_path et stock_articles_url.

C'est vérifiable avec la commande rake routes.

Cela n'étant pas très élégant, on écrira ces routes avec namespace et lui définir un params par défaut qui existera systématiquement dans ce namespace.
namespace :stock, :namespace => :stock do
resources :articles
end
Et voilà avec 2 options en moins et une meilleure lisibilité de notre fichier de route, nous avons le même comportement.
Ensuite on fait la même chose sur 'vente' ou on boucle sur un Array [:stock, :vente].

Cette fonctionnalité ouvre de nombreuses portes.
En effet quelque soit le type de routes écrites avec 'match', 'get' et tout autre verbe RESTFul, on peut définir un params par défaut pour celle-ci en ajoutant
:nom_du_param => valeur_du_param.
Voilà pour la petite astuce, en espérant qu'elle soit utile au plus grand nombre.

Aucun commentaire: