Le routage de ressources en Rails
Posté par Nicolas le 01 novembre 2011
Le routage de ressources en Rails permet de déclarer très rapidement l'ensemble des routes pour un contrôleur qui respecte l'architecture REST. Cet article présente comment définir les routes pour des ressources.
- Avoir compris le fonctionnement des routes en rails
- Un rappel sur REST
- Définir des routes pour des ressources
- Ajouter des routes pour des actions spécifiques aux ressources
Rappel sur les ressources et sur REST
Notion de ressource
La notion de ressource est vague et donc de difficile à définir. Prenons la première définition explicite du terme ressource dans son sens le plus général donnée par Tim berners Lee :
Une ressource peut être toute chose qui possède une identité. Des exemples familiers incluent un document électronique, une image, un service (par exemple "le bulletin météo d'aujourd'hui pour Los Angeles"), ou un ensemble d'autres ressources. Certaines ressources ne peuvent pas être "ramenées par le réseau" (network retrievable), par exemple les êtres humains, les entreprises, les livres d'une bibliothèque peuvent être aussi considérés comme des ressources.
Ce qu'il est important de comprendre c'est qu'une ressource est finalement n'importe quoi que l'on peut identifier de manière unique par une URI (Uniform Resource Identifier). Sur le web, cet identifiant unique est généralement une URL.
Même si cette notion paraît difficile à appréhender aux premiers abords, elle vous paraîtra plus claire une fois utilisée dans une application. Passons donc à la suite et à une approche de l'architecture REST.
Notion de REST
REST est un style architectural, une manière de construire une application pour le web. Les principes essentiels d'une architecture REST sont les suivants :
- Chaque ressource doit être identifiée de manière unique par une URI.
-
Les méthodes HTTP
GET,POST,PUTetDELETEsuffisent pour accéder à et modifier une ressource.
Exemple d'application RESTful
Je pense qu'il n'y a pas plus parlant qu'un exemple pour comprendre ce qu'est l'architecture REST et ce qu'est une ressource.
Prenons donc l'exemple d'un blog contenant plusieurs articles. Ici, les ressources à manipuler sont les articles. Dans ce blog on peut ajouter, modifier, lire, et supprimer des articles. Chaque article a un identifiant unique, ici c'est son nom. Donc, pour que l'application respecte l'architecture REST elle doit permettre les actions suivantes :
- Lire un article - on effectue une requête de type
GETsur http://monblog.fr/articles/nom-de-mon-article. Le nom de l'article étant son identifiant unique. - Écrire un article - on effectue une requête de type
POSTsur http://monblog.fr/articles/. Le contenu du messagePOSTreprésentant le contenu du nouvel article à créer. - Modifier un article - on effectue une requête de type
PUTsur http://monblog.fr/articles/nom-de-mon-article. Le contenu du messagePUTreprésentant le contenu modifié de l'article. - Supprimer un article - on effectue une requête de type
DELETEsur http://monblog.fr/articles/nom-de-mon-article.
Si vous avez besoin de plus d'informations au sujet de REST reportez vous à la section REST de l'article Avant de commencer avec Ruby On Rails
Les routes pour des ressources
CRUD, méthodes HTTP et actions
En Rails, le routage de ressources fournit une correspondance entre les verbes HTTP et les URLs avec les actions du contrôleur. Par convention, chaque action du contrôleur correspond à une opération CRUD (create, read, update, destroy) dans la base de données.
Prenons un exemple, supposons que nous avons un blog contenant des articles qui sont ici les ressources à manipuler. Voici comment définir les routes pour ce type de ressources :
# config/routes.rb resources :articles
Cette seule règle permet de définir les routes pour les actions index, show, new, edit, create, update et destroy, qui sont les actions typiques que l'on doit pouvoir effectuer sur une ressource.
Nous obtenons les sept routes suivantes qui s'appliquent toutes au contrôleur articles_controller :
| Méthode HTTP |
URL | Action | Utilité |
|---|---|---|---|
| GET | /articles | index | Afficher la liste de tous les articles |
| GET | /articles/new | new | Afficher un formulaire pour créer un article |
| POST | /articles | create | Créer un nouvel article à partir du contenu du message POST |
| GET | /articles/:id | show | Afficher l'article ayant pour id celle passée dans l'URL |
| GET | /articles/:id/edit | edit | Afficher un formulaire pour editer l'article ayant pour id celle passée dans l'URL |
| PUT | /articles/:id | update | Mettre à jour un article ayant pour id celle passée dans l'URL à partir du corps du message PUT |
| DELETE | /articles/:id | destroy | Supprimer l'article ayant pour id celle passée dans l'URL |
Il est important de savoir qu'il y a une priorité sur les règles. Les règles écrites au début du fichier sont prioritaires par rapport à celles écrites en dessous.
Chemins et URLs générés
Comme pour toutes les routes, le routage de ressources génère des chemins et des URLs. Voici un tableau récapitulatif de ces helpers et des actions vers lesquelles ils redirigent en fonction du verbe HTTP employé :
| Path helper | Méthode HTTP |
Action |
|---|---|---|
| articles_path | GET | index |
| POST | create | |
| article_path(:id) Ce path prend en paramètre l'id de l'article à modifier | GET | show |
| PUT | update | |
| DELETE | destroy | |
| new_article_path | GET | new |
| edit_article_path | GET | edit |
Comme tous les routes helpers, il y a aussi les URLs helpers qui sont générés. Pour s'en servir, il suffit de remplacer …_path par …_url. Par exemple, new_article_url.
Exemple d'utilisations
Le routage de ressource est utilisé par Rails lorsque l'on crée un scaffold. Rails génère les routes, le modèle, la table en base de données, les actions RESTful dans le contrôleur et les vues. Donc pour voir un bon exemple des path_heplers, il suffit de regarder dans les vues générées.
Par exemple, si on crée le scaffold suivant :
$ rails generate scaffold Article title:string content:text
On peut constater l'utilisation des path_helpers suivants :
# app/views/articles/index.html.erb ... <%= link_to 'New Article', new_article_path %> ...
# app/views/articles/show.html.erb ... # Ici @article est défini dans la méthode show du contrôleur articles_controller <%= link_to 'Edit', edit_article_path(@article) %> | <%= link_to 'Back', articles_path %> ...
# app/views/articles/show.html.erb ... # Ici @article est défini dans la méthode edit du contrôleur articles_controller <%= link_to 'Show', @article %> | <%= link_to 'Back', articles_path %> ...
Pour le dernier exemple, on peut voir que le lien pour l'action show n'utilise pas le path_helper article_path(@article). Ceci est dû au fait que Rails comprend tout seul que lorsqu'on lui passe directement une instance de l'objet Article il doit utiliser le path_helper article_path et donc on fonction de la méthode HTTP utilisé il redirigera vers la bonne action du contrôleur. Ici c'est un lien donc c'est la méthode GET qui est utilisé et donc ce lien redirigera vers l'action show.
Définir plusieurs ressources
Le routeur Rails nous permet de définir plusieurs ressources en une seule ligne de la façon suivante :
resources :articles, :photos, :authors
Les routes pour une ressource unique
CRUD, méthodes HTTP et actions
Il peut arriver que l'on ait besoin de définir les routes pour une ressource unique à laquelle on aimerait accéder sans préciser une ID. Le routeur Rails nous permet de définir ce genre de route. Prenons un exemple pour voir l'ensemble des routes créées.
# config/routes.rb resource :account
Faire attention, dans ce cas il n'y a pas de « s » au mot resource
Cette seule règle permet de définir les routes pour les actions show, new, edit, create, update et destroy du contrôleur accounts_controller. Voici un récapitulatif :
| Méthode HTTP |
URL | Action | Utilité |
|---|---|---|---|
| GET | /account/new | new | Afficher un formulaire pour créer un compte |
| POST | /account | create | Créer le nouveau compte à partir du contenu du message POST |
| GET | /account | show | Afficher le seul et unique compte |
| GET | /account/edit | edit | Afficher un formulaire pour editer le compte |
| PUT | /account | update | Mettre à jour le seul et unique compte à partir du contenu du message PUT |
| DELETE | /account | destroy | Supprimer le compte |
Chemins et URLs générés
Dans la ces d'une ressource unique, les path_helpers générés ne prennent pas de paramètre étant donné que la ressource à modifier est toujours la même. Voici un tableau récapitulatif de ces helpers et des actions vers lesquelles ils redirigent en fonction du verbe HTTP employé :
| Path helper | Méthode HTTP |
Action |
|---|---|---|
| account_path | GET | show |
| POST | create | |
| PUT | update | |
| DELETE | destroy | |
| new_account_path | GET | new |
| edit_account_path | GET | edit |
Ajouter des actions RESTful
Il arrive souvent que l'on ait besoin d'ajouter des routes à une ressource pour des actions autres que celles définies par défaut. Le routeur Rails nous permet de le faire très simplement, voyons comment.
Ajout d'une action sur la collection
Tout d'abord, il faut définir si cette action va agir sur l'ensemble des ressources ou seulement sur une seule. Prenons un exemple, supposons que l'on ait un contrôleur photos_controller et que l'on veuille ajouter la possiblité de faire une recherche sur les photos. Dans ce cas, l'action sera effectuée sur l'ensemble des ressources photos. Donc on défini les routes comme ceci :
resources :photos do get 'search', :on => :collection end
Il est possible d'utiliser des symboles à la place des chaînes de caractères. Par exemple, on pourrait écrire :
get :search, :on => :collection
Ajout d'une action sur un membre
Supposons maintenant que l'on veuille effectuer une action sur une seule ressource, par exemple accéder à une previsualisation d'une photo. Dans ce cas on peux définir les routes comme ceci :
resources :photos do get 'preview', :on => :member end
Les routes helpers obtenus dans les deux cas précédents sont respectivement search_photos_path et preview_photo_path. Bien faire attention au « s » à la fin de photos que l'on met que lorsque l'action est sur la collection entière.
Si on a beaucoup d'actions à ajouter sur les membres ou sur la collection entière on peut également définir les routes comme ceci :
resources :photos do
member do
get 'preview'
get 'buy'
end
collection do
get 'search'
get 'another_action'
end
end
Il faut noter ici que l'on peut remplacer let mot get par les autres méthodes HTTP, par exemple post
Voilà les bases pour le routage de ressources en Rails, je publierai prochainement un article sur les ressources imbriquées. Si vous avez des questions ou améliorations à proposer n'hésitez pas à laissez un commentaire.