edge
Plus sur rubyonrails.org: Plus de Ruby on Rails

Rails Routing de l'extérieur vers l'intérieur

Ce guide couvre les fonctionnalités de routage de Rails accessibles aux utilisateurs.

Après avoir lu ce guide, vous saurez :

Chapters

  1. Le but du routeur de Rails
  2. Routage des ressources : la valeur par défaut de Rails
  3. Routes non ressourceful
  4. Personnalisation des routes de ressources
  5. Diviser un fichier de routes très volumineux en plusieurs fichiers plus petits
  6. Inspection et test des routes

1 Le but du routeur de Rails

Le routeur de Rails reconnaît les URL et les envoie vers une action du contrôleur ou vers une application Rack. Il peut également générer des chemins et des URL, évitant ainsi la nécessité de coder en dur des chaînes dans vos vues.

1.1 Connecter les URL au code

Lorsque votre application Rails reçoit une requête entrante pour :

GET /patients/17

elle demande au routeur de l'associer à une action du contrôleur. Si la première route correspondante est :

get '/patients/:id', to: 'patients#show'

la requête est envoyée à l'action show du contrôleur patients avec { id: '17' } dans params.

NOTE : Rails utilise snake_case pour les noms de contrôleur ici, si vous avez un contrôleur à plusieurs mots comme MonsterTrucksController, vous devez utiliser monster_trucks#show par exemple.

1.2 Générer des chemins et des URL à partir du code

Vous pouvez également générer des chemins et des URL. Si la route ci-dessus est modifiée comme suit :

get '/patients/:id', to: 'patients#show', as: 'patient'

et que votre application contient ce code dans le contrôleur :

@patient = Patient.find(params[:id])

et ceci dans la vue correspondante :

<%= link_to 'Dossier du patient', patient_path(@patient) %>

alors le routeur générera le chemin /patients/17. Cela réduit la fragilité de votre vue et rend votre code plus facile à comprendre. Notez que l'identifiant n'a pas besoin d'être spécifié dans l'assistant de route.

1.3 Configuration du routeur de Rails

Les routes de votre application ou de votre moteur se trouvent dans le fichier config/routes.rb et ressemblent généralement à ceci :

Rails.application.routes.draw do
  resources :brands, only: [:index, :show] do
    resources :products, only: [:index, :show]
  end

  resource :basket, only: [:show, :update, :destroy]

  resolve("Basket") { route_for(:basket) }
end

Comme il s'agit d'un fichier source Ruby classique, vous pouvez utiliser toutes ses fonctionnalités pour vous aider à définir vos routes, mais faites attention aux noms de variables car ils peuvent entrer en conflit avec les méthodes DSL du routeur.

NOTE : Le bloc Rails.application.routes.draw do ... end qui enveloppe vos définitions de routes est nécessaire pour établir la portée du DSL du routeur et ne doit pas être supprimé.

2 Routage des ressources : la valeur par défaut de Rails

Le routage des ressources vous permet de déclarer rapidement toutes les routes courantes pour un contrôleur de ressources donné. Un seul appel à resources peut déclarer toutes les routes nécessaires pour vos actions index, show, new, edit, create, update et destroy.

2.1 Ressources sur le Web

Les navigateurs demandent des pages à Rails en faisant une requête pour une URL en utilisant une méthode HTTP spécifique, telle que GET, POST, PATCH, PUT et DELETE. Chaque méthode est une demande d'effectuer une opération sur la ressource. Une route de ressource associe un certain nombre de requêtes liées à des actions dans un seul contrôleur.

Lorsque votre application Rails reçoit une requête entrante pour :

DELETE /photos/17

elle demande au routeur de l'associer à une action du contrôleur. Si la première route correspondante est :

resources :photos

Rails enverrait cette requête à l'action destroy du contrôleur photos avec { id: '17' } dans params.

2.2 CRUD, Verbes et Actions

Dans Rails, une route de ressource fournit une correspondance entre les verbes HTTP et les URL vers des actions de contrôleur. Par convention, chaque action est également associée à une opération CRUD spécifique dans une base de données. Une seule entrée dans le fichier de routage, telle que :

resources :photos

crée sept routes différentes dans votre application, toutes mappées sur le contrôleur Photos :

Verbe HTTP Chemin Contrôleur#Action Utilisé pour
GET /photos photos#index afficher une liste de toutes les photos
GET /photos/new photos#new renvoyer un formulaire HTML pour créer une nouvelle photo
POST /photos photos#create créer une nouvelle photo
GET /photos/:id photos#show afficher une photo spécifique
GET /photos/:id/edit photos#edit renvoyer un formulaire HTML pour modifier une photo
PATCH/PUT /photos/:id photos#update mettre à jour une photo spécifique
DELETE /photos/:id photos#destroy supprimer une photo spécifique

NOTE : Étant donné que le routeur utilise la méthode HTTP et l'URL pour faire correspondre les requêtes entrantes, quatre URL correspondent à sept actions différentes.

NOTE : Les routes Rails sont associées dans l'ordre où elles sont spécifiées, donc si vous avez une ligne resources :photos au-dessus d'un get 'photos/poll', la route de l'action show pour la ligne resources sera associée avant la ligne get. Pour corriger cela, déplacez la ligne get au-dessus de la ligne resources afin qu'elle soit associée en premier.

2.3 Aide pour les chemins et les URL

La création d'une route de ressource expose également un certain nombre d'aides aux contrôleurs de votre application. Dans le cas de resources :photos :

  • photos_path renvoie /photos
  • new_photo_path renvoie /photos/new
  • edit_photo_path(:id) renvoie /photos/:id/edit (par exemple, edit_photo_path(10) renvoie /photos/10/edit)
  • photo_path(:id) renvoie /photos/:id (par exemple, photo_path(10) renvoie /photos/10)

Chacune de ces aides a une aide correspondante _url (comme photos_url) qui renvoie le même chemin précédé de l'hôte, du port et du préfixe de chemin actuels.

CONSEIL : Pour trouver les noms des aides de route pour vos routes, voir Listing existing routes ci-dessous.

2.4 Définition de plusieurs ressources en même temps

Si vous avez besoin de créer des routes pour plus d'une ressource, vous pouvez économiser un peu de frappe en les définissant toutes avec un seul appel à resources :

resources :photos, :books, :videos

Cela fonctionne exactement de la même manière que :

resources :photos
resources :books
resources :videos

2.5 Ressources singulières

Parfois, vous avez une ressource que les clients recherchent toujours sans référencer un ID. Par exemple, vous souhaitez que /profile affiche toujours le profil de l'utilisateur actuellement connecté. Dans ce cas, vous pouvez utiliser une ressource singulière pour faire correspondre /profile (plutôt que /profile/:id) à l'action show :

get 'profile', to: 'users#show'

Le fait de passer une String à to: attend un format controller#action. Lorsque vous utilisez un Symbol, l'option to: doit être remplacée par action:. Lorsque vous utilisez une String sans #, l'option to: doit être remplacée par controller: :

get 'profile', action: :show, controller: 'users'

Cette route de ressource :

resource :geocoder
resolve('Geocoder') { [:geocoder] }

crée six routes différentes dans votre application, toutes mappées sur le contrôleur Geocoders :

Méthode HTTP Chemin Contrôleur#Action Utilisé pour
GET /geocoder/new geocoders#new renvoie un formulaire HTML pour créer le géocodeur
POST /geocoder geocoders#create crée le nouveau géocodeur
GET /geocoder geocoders#show affiche la ressource unique du géocodeur
GET /geocoder/edit geocoders#edit renvoie un formulaire HTML pour modifier le géocodeur
PATCH/PUT /geocoder geocoders#update met à jour la ressource unique du géocodeur
DELETE /geocoder geocoders#destroy supprime la ressource du géocodeur

NOTE : Étant donné que vous pouvez vouloir utiliser le même contrôleur pour une route singulière (/account) et une route plurielle (/accounts/45), les ressources singulières sont mappées sur des contrôleurs pluriels. Ainsi, par exemple, resource :photo et resources :photos créent à la fois des routes singulières et plurielles qui sont mappées sur le même contrôleur (PhotosController).

Une route de ressource singulière génère ces aides :

  • new_geocoder_path renvoie /geocoder/new
  • edit_geocoder_path renvoie /geocoder/edit
  • geocoder_path renvoie /geocoder

NOTE : L'appel à resolve est nécessaire pour convertir les instances de Geocoder en routes via l'identification des enregistrements.

Comme pour les ressources plurielles, les mêmes aides se terminant par _url incluront également l'hôte, le port et le préfixe de chemin.

2.6 Espaces de noms des contrôleurs et routage

Vous pouvez souhaiter organiser des groupes de contrôleurs sous un espace de noms. Le plus souvent, vous regroupez un certain nombre de contrôleurs d'administration sous un espace de noms Admin:: et placez ces contrôleurs sous le répertoire app/controllers/admin. Vous pouvez router vers un tel groupe en utilisant un bloc namespace :

namespace :admin do
  resources :articles, :comments
end

Cela créera un certain nombre de routes pour chacun des contrôleurs articles et comments. Pour Admin::ArticlesController, Rails créera :

Méthode HTTP Chemin Contrôleur#Action Aide de route nommée
GET /admin/articles admin/articles#index admin_articles_path
GET /admin/articles/new admin/articles#new new_admin_article_path
POST /admin/articles admin/articles#create admin_articles_path
GET /admin/articles/:id admin/articles#show admin_article_path(:id)
GET /admin/articles/:id/edit admin/articles#edit edit_admin_article_path(:id)
PATCH/PUT /admin/articles/:id admin/articles#update admin_article_path(:id)
DELETE /admin/articles/:id admin/articles#destroy admin_article_path(:id)

Si vous souhaitez plutôt router /articles (sans le préfixe /admin) vers Admin::ArticlesController, vous pouvez spécifier le module avec un bloc scope :

scope module: 'admin' do
  resources :articles, :comments
end

Cela peut également être fait pour une seule route :

resources :articles, module: 'admin'

Si vous souhaitez plutôt router /admin/articles vers ArticlesController (sans le préfixe du module Admin::), vous pouvez spécifier le chemin avec un bloc scope :

scope '/admin' do
  resources :articles, :comments
end

Cela peut également être fait pour une seule route :

resources :articles, path: '/admin/articles'

Dans ces deux cas, les helpers de route nommés restent les mêmes que si vous n'utilisiez pas scope. Dans le dernier cas, les chemins suivants sont mappés vers ArticlesController :

Verbe HTTP Chemin Contrôleur#Action Helper de route nommé
GET /admin/articles articles#index articles_path
GET /admin/articles/new articles#new new_article_path
POST /admin/articles articles#create articles_path
GET /admin/articles/:id articles#show article_path(:id)
GET /admin/articles/:id/edit articles#edit edit_article_path(:id)
PATCH/PUT /admin/articles/:id articles#update article_path(:id)
DELETE /admin/articles/:id articles#destroy article_path(:id)

CONSEIL : Si vous avez besoin d'utiliser un espace de noms de contrôleur différent à l'intérieur d'un bloc namespace, vous pouvez spécifier un chemin de contrôleur absolu, par exemple : get '/foo', to: '/foo#index'.

2.7 Ressources imbriquées

Il est courant d'avoir des ressources qui sont logiquement des enfants d'autres ressources. Par exemple, supposons que votre application inclut ces modèles :

class Magazine < ApplicationRecord
  has_many :ads
end

class Ad < ApplicationRecord
  belongs_to :magazine
end

Les routes imbriquées vous permettent de capturer cette relation dans votre routage. Dans ce cas, vous pourriez inclure cette déclaration de route :

resources :magazines do
  resources :ads
end

En plus des routes pour les magazines, cette déclaration routera également les annonces vers un AdsController. Les URLs des annonces nécessitent un magazine :

Verbe HTTP Chemin Contrôleur#Action Utilisé pour
GET /magazines/:magazine_id/ads ads#index afficher une liste de toutes les annonces pour un magazine spécifique
GET /magazines/:magazine_id/ads/new ads#new renvoyer un formulaire HTML pour créer une nouvelle annonce appartenant à un magazine spécifique
POST /magazines/:magazine_id/ads ads#create créer une nouvelle annonce appartenant à un magazine spécifique
GET /magazines/:magazine_id/ads/:id ads#show afficher une annonce spécifique appartenant à un magazine spécifique
GET /magazines/:magazine_id/ads/:id/edit ads#edit renvoyer un formulaire HTML pour modifier une annonce appartenant à un magazine spécifique
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update mettre à jour une annonce spécifique appartenant à un magazine spécifique
DELETE /magazines/:magazine_id/ads/:id ads#destroy supprimer une annonce spécifique appartenant à un magazine spécifique

Cela créera également des helpers de routage tels que magazine_ads_url et edit_magazine_ad_path. Ces helpers prennent une instance de Magazine en premier paramètre (magazine_ads_url(@magazine)).

2.7.1 Limites de l'imbrication

Vous pouvez imbriquer des ressources dans d'autres ressources imbriquées si vous le souhaitez. Par exemple :

resources :publishers do
  resources :magazines do
    resources :photos
  end
end

Les ressources profondément imbriquées deviennent rapidement fastidieuses. Dans ce cas, par exemple, l'application reconnaîtrait des chemins tels que :

/publishers/1/magazines/2/photos/3

Le helper de route correspondant serait publisher_magazine_photo_url, ce qui vous obligerait à spécifier des objets aux trois niveaux. En effet, cette situation est assez confuse pour qu'un article populaire de Jamis Buck propose une règle de base pour une bonne conception Rails :

CONSEIL : Les ressources ne doivent jamais être imbriquées à plus d'un niveau de profondeur.

2.7.2 Imbrication superficielle

Une façon d'éviter l'imbrication profonde (comme recommandé ci-dessus) consiste à générer les actions de collection sous la portée du parent, de manière à avoir une idée de la hiérarchie, mais à ne pas imbriquer les actions des membres. En d'autres termes, construire uniquement des routes avec le minimum d'informations pour identifier de manière unique la ressource, comme ceci :

resources :articles do
  resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]

Cette idée trouve un équilibre entre des routes descriptives et une imbrication profonde. Il existe une syntaxe abrégée pour y parvenir, via l'option :shallow :

resources :articles do
  resources :comments, shallow: true
end

Cela générera exactement les mêmes routes que le premier exemple. Vous pouvez également spécifier l'option :shallow dans la ressource parent, auquel cas toutes les ressources imbriquées seront superficielles :

resources :articles, shallow: true do
  resources :comments
  resources :quotes
  resources :drafts
end

La ressource articles aura les routes suivantes générées pour elle :

Verbe HTTP Chemin Contrôleur#Action Aide à la route nommée
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /comments/:id/edit(.:format) comments#edit edit_comment_path
GET /comments/:id(.:format) comments#show comment_path
PATCH/PUT /comments/:id(.:format) comments#update comment_path
DELETE /comments/:id(.:format) comments#destroy comment_path
GET /articles/:article_id/quotes(.:format) quotes#index article_quotes_path
POST /articles/:article_id/quotes(.:format) quotes#create article_quotes_path
GET /articles/:article_id/quotes/new(.:format) quotes#new new_article_quote_path
GET /quotes/:id/edit(.:format) quotes#edit edit_quote_path
GET /quotes/:id(.:format) quotes#show quote_path
PATCH/PUT /quotes/:id(.:format) quotes#update quote_path
DELETE /quotes/:id(.:format) quotes#destroy quote_path
GET /articles/:article_id/drafts(.:format) drafts#index article_drafts_path
POST /articles/:article_id/drafts(.:format) drafts#create article_drafts_path
GET /articles/:article_id/drafts/new(.:format) drafts#new new_article_draft_path
GET /drafts/:id/edit(.:format) drafts#edit edit_draft_path
GET /drafts/:id(.:format) drafts#show draft_path
PATCH/PUT /drafts/:id(.:format) drafts#update draft_path
DELETE /drafts/:id(.:format) drafts#destroy draft_path
GET /articles(.:format) articles#index articles_path
POST /articles(.:format) articles#create articles_path
GET /articles/new(.:format) articles#new new_article_path
GET /articles/:id/edit(.:format) articles#edit edit_article_path
GET /articles/:id(.:format) articles#show article_path
PATCH/PUT /articles/:id(.:format) articles#update article_path
DELETE /articles/:id(.:format) articles#destroy article_path

La méthode shallow de la DSL crée une portée à l'intérieur de laquelle chaque imbrication est superficielle. Cela génère les mêmes routes que l'exemple précédent :

shallow do
  resources :articles do
    resources :comments
    resources :quotes
    resources :drafts
  end
end

Il existe deux options pour scope pour personnaliser les routes superficielles. :shallow_path préfixe les chemins des membres avec le paramètre spécifié :

scope shallow_path: "sekret" do
  resources :articles do
    resources :comments, shallow: true
  end
end

La ressource comments aura les routes suivantes générées pour elle :

Verbe HTTP Chemin Contrôleur#Action Aide à la route nommée
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /sekret/comments/:id/edit(.:format) comments#edit edit_comment_path
GET /sekret/comments/:id(.:format) comments#show comment_path
PATCH/PUT /sekret/comments/:id(.:format) comments#update comment_path
DELETE /sekret/comments/:id(.:format) comments#destroy comment_path

L'option :shallow_prefix ajoute le paramètre spécifié aux aides de route nommées :

scope shallow_prefix: "sekret" do
  resources :articles do
    resources :comments, shallow: true
  end
end

La ressource comments aura les routes suivantes générées pour elle :

Verbe HTTP Chemin Contrôleur#Action Aide à la route nommée
GET /articles/:article_id/comments(.:format) comments#index article_comments_path
POST /articles/:article_id/comments(.:format) comments#create article_comments_path
GET /articles/:article_id/comments/new(.:format) comments#new new_article_comment_path
GET /comments/:id/edit(.:format) comments#edit edit_sekret_comment_path
GET /comments/:id(.:format) comments#show sekret_comment_path
PATCH/PUT /comments/:id(.:format) comments#update sekret_comment_path
DELETE /comments/:id(.:format) comments#destroy sekret_comment_path

2.8 Préoccupations de routage

Les préoccupations de routage vous permettent de déclarer des routes communes qui peuvent être réutilisées dans d'autres ressources et routes. Pour définir une préoccupation, utilisez un bloc concern :

concern :commentable do
  resources :comments
end

concern :image_attachable do
  resources :images, only: :index
end

Ces préoccupations peuvent être utilisées dans les ressources pour éviter la duplication de code et partager le comportement entre les routes :

resources :messages, concerns: :commentable

resources :articles, concerns: [:commentable, :image_attachable]

Ce qui précède est équivalent à :

resources :messages do
  resources :comments
end

resources :articles do
  resources :comments
  resources :images, only: :index
end

Vous pouvez également les utiliser n'importe où en appelant concerns. Par exemple, dans un bloc scope ou namespace :

namespace :articles do
  concerns :commentable
end

2.9 Création de chemins et d'URL à partir d'objets

En plus d'utiliser les helpers de routage, Rails peut également créer des chemins et des URL à partir d'un tableau de paramètres. Par exemple, supposons que vous ayez cet ensemble de routes :

resources :magazines do
  resources :ads
end

Lorsque vous utilisez magazine_ad_path, vous pouvez passer des instances de Magazine et Ad au lieu des identifiants numériques :

<%= link_to 'Détails de l'annonce', magazine_ad_path(@magazine, @ad) %>

Vous pouvez également utiliser url_for avec un ensemble d'objets, et Rails déterminera automatiquement quelle route vous souhaitez :

<%= link_to 'Détails de l'annonce', url_for([@magazine, @ad]) %>

Dans ce cas, Rails verra que @magazine est un Magazine et @ad est un Ad et utilisera donc l'helper magazine_ad_path. Dans les helpers comme link_to, vous pouvez spécifier simplement l'objet à la place de l'appel complet à url_for :

<%= link_to 'Détails de l'annonce', [@magazine, @ad] %>

Si vous souhaitez créer un lien vers un magazine uniquement :

<%= link_to 'Détails du magazine', @magazine %>

Pour les autres actions, vous devez simplement insérer le nom de l'action en tant que premier élément du tableau :

<%= link_to 'Modifier l'annonce', [:edit, @magazine, @ad] %>

Cela vous permet de traiter les instances de vos modèles comme des URL, et constitue un avantage clé de l'utilisation du style ressource.

2.10 Ajout de plus d'actions RESTful

Vous n'êtes pas limité aux sept routes que le routage RESTful crée par défaut. Si vous le souhaitez, vous pouvez ajouter des routes supplémentaires qui s'appliquent à la collection ou aux membres individuels de la collection.

2.10.1 Ajout de routes membres

Pour ajouter une route membre, ajoutez simplement un bloc member dans le bloc de la ressource :

resources :photos do
  member do
    get 'preview'
  end
end

Cela reconnaîtra /photos/1/preview avec GET, et routera vers l'action preview de PhotosController, avec la valeur de l'identifiant de la ressource passée dans params[:id]. Il créera également les helpers preview_photo_url et preview_photo_path.

Dans le bloc des routes membres, chaque nom de route spécifie la méthode HTTP qui sera reconnue. Vous pouvez utiliser get, patch, put, post, ou delete ici. Si vous n'avez pas plusieurs routes member, vous pouvez également passer :on à une route, en éliminant le bloc :

resources :photos do
  get 'preview', on: :member
end

Vous pouvez omettre l'option :on, cela créera la même route membre à l'exception de la valeur de l'identifiant de la ressource qui sera disponible dans params[:photo_id] au lieu de params[:id]. Les helpers de route seront également renommés de preview_photo_url et preview_photo_path en photo_preview_url et photo_preview_path.

2.10.2 Ajout de routes de collection

Pour ajouter une route à la collection, utilisez un bloc collection :

resources :photos do
  collection do
    get 'search'
  end
end

Cela permettra à Rails de reconnaître des chemins tels que /photos/search avec GET, et routera vers l'action search de PhotosController. Il créera également les helpers de route search_photos_url et search_photos_path.

Tout comme avec les routes membres, vous pouvez passer :on à une route :

resources :photos do
  get 'search', on: :collection
end

NOTE : Si vous définissez des routes de ressource supplémentaires avec un symbole en tant que premier argument positionnel, soyez conscient que ce n'est pas équivalent à utiliser une chaîne de caractères. Les symboles infèrent les actions du contrôleur tandis que les chaînes infèrent les chemins.

2.10.3 Ajout de routes pour des actions nouvelles supplémentaires

Pour ajouter une action nouvelle alternative en utilisant le raccourci :on :

resources :comments do
  get 'preview', on: :new
end

Cela permettra à Rails de reconnaître des chemins tels que /comments/new/preview avec GET, et routera vers l'action preview de CommentsController. Il créera également les helpers preview_new_comment_url et preview_new_comment_path.

CONSEIL : Si vous vous retrouvez à ajouter de nombreuses actions supplémentaires à une route ressource, il est temps de vous arrêter et de vous demander si vous ne masquez pas la présence d'une autre ressource.

3 Routes non ressourceful

En plus du routage des ressources, Rails offre une prise en charge puissante pour router des URL arbitraires vers des actions. Ici, vous n'obtenez pas de groupes de routes générés automatiquement par le routage des ressources. Au lieu de cela, vous configurez chaque route séparément dans votre application.

Bien que vous devriez généralement utiliser le routage des ressources, il existe encore de nombreux cas où le routage plus simple est plus approprié. Il n'est pas nécessaire d'essayer de faire rentrer chaque dernier morceau de votre application dans un framework ressourceful si cela ne convient pas. En particulier, le routage simple facilite grandement la correspondance des URL héritées avec les nouvelles actions de Rails.

3.1 Paramètres liés

Lorsque vous configurez une route régulière, vous fournissez une série de symboles que Rails associe à des parties d'une requête HTTP entrante. Par exemple, considérez cette route :

get 'photos(/:id)', to: 'photos#display'

Si une requête entrante de /photos/1 est traitée par cette route (parce qu'elle n'a pas correspondu à une route précédente dans le fichier), alors le résultat sera d'appeler l'action display du PhotosController, et de rendre le paramètre final "1" disponible en tant que params[:id]. Cette route routera également la requête entrante de /photos vers PhotosController#display, car :id est un paramètre facultatif, indiqué par des parenthèses.

3.2 Segments dynamiques

Vous pouvez configurer autant de segments dynamiques que vous le souhaitez dans une route régulière. Tout segment sera disponible pour l'action en tant que partie de params. Si vous configurez cette route :

get 'photos/:id/:user_id', to: 'photos#show'

Un chemin entrant de /photos/1/2 sera envoyé à l'action show du PhotosController. params[:id] sera "1", et params[:user_id] sera "2".

CONSEIL : Par défaut, les segments dynamiques n'acceptent pas les points - cela est dû au fait que le point est utilisé comme séparateur pour les routes formatées. Si vous avez besoin d'utiliser un point à l'intérieur d'un segment dynamique, ajoutez une contrainte qui annule cela - par exemple, id: /[^\/]+/ permet tout sauf une barre oblique.

3.3 Segments statiques

Vous pouvez spécifier des segments statiques lors de la création d'une route en ne préfixant pas un deux-points à un segment :

get 'photos/:id/with_user/:user_id', to: 'photos#show'

Cette route répondrait aux chemins tels que /photos/1/with_user/2. Dans ce cas, params serait { controller: 'photos', action: 'show', id: '1', user_id: '2' }.

3.4 La chaîne de requête

Les params incluront également tous les paramètres de la chaîne de requête. Par exemple, avec cette route :

get 'photos/:id', to: 'photos#show'

Un chemin entrant de /photos/1?user_id=2 sera envoyé à l'action show du contrôleur Photos. params sera { controller: 'photos', action: 'show', id: '1', user_id: '2' }.

3.5 Définition des valeurs par défaut

Vous pouvez définir des valeurs par défaut dans une route en fournissant un hash pour l'option :defaults. Cela s'applique même aux paramètres que vous ne spécifiez pas en tant que segments dynamiques. Par exemple :

get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' }

Rails ferait correspondre photos/12 à l'action show de PhotosController, et définirait params[:format] sur "jpg".

Vous pouvez également utiliser un bloc defaults pour définir les valeurs par défaut pour plusieurs éléments :

defaults format: :json do
  resources :photos
end

REMARQUE : Vous ne pouvez pas remplacer les valeurs par défaut via les paramètres de la chaîne de requête - cela est pour des raisons de sécurité. Les seules valeurs par défaut qui peuvent être remplacées sont les segments dynamiques via la substitution dans le chemin de l'URL.

3.6 Nommer les routes

Vous pouvez spécifier un nom pour n'importe quelle route en utilisant l'option :as :

get 'exit', to: 'sessions#destroy', as: :logout

Cela créera logout_path et logout_url en tant qu'aides de route nommées dans votre application. Appeler logout_path renverra /exit

Vous pouvez également utiliser cela pour remplacer les méthodes de routage définies par les ressources en plaçant des routes personnalisées avant que la ressource ne soit définie, comme ceci :

get ':username', to: 'users#show', as: :user
resources :users

Cela définira une méthode user_path qui sera disponible dans les contrôleurs, les aides et les vues et qui ira vers une route telle que /bob. À l'intérieur de l'action show de UsersController, params[:username] contiendra le nom d'utilisateur de l'utilisateur. Modifiez :username dans la définition de la route si vous ne souhaitez pas que le nom de votre paramètre soit :username.

3.7 Contraintes de verbe HTTP

En général, vous devriez utiliser les méthodes get, post, put, patch et delete pour contraindre une route à un verbe particulier. Vous pouvez utiliser la méthode match avec l'option :via pour faire correspondre plusieurs verbes à la fois :

match 'photos', to: 'photos#show', via: [:get, :post]

Vous pouvez faire correspondre tous les verbes à une route particulière en utilisant via: :all :

match 'photos', to: 'photos#show', via: :all

REMARQUE : Faire correspondre à la fois les requêtes GET et POST à une seule action présente des implications en termes de sécurité. En général, vous devriez éviter de faire correspondre tous les verbes à une action à moins d'avoir une bonne raison de le faire.

REMARQUE : GET dans Rails ne vérifiera pas le jeton CSRF. Vous ne devriez jamais écrire dans la base de données à partir de requêtes GET, pour plus d'informations, consultez le guide de sécurité sur les contre-mesures CSRF.

3.8 Contraintes de segment

Vous pouvez utiliser l'option :constraints pour imposer un format à un segment dynamique :

get 'photos/:id', to: 'photos#show', constraints: { id: /[A-Z]\d{5}/ }

Cette route correspondrait aux chemins tels que /photos/A12345, mais pas à /photos/893. Vous pouvez exprimer de manière plus concise la même route de cette manière :

get 'photos/:id', to: 'photos#show', id: /[A-Z]\d{5}/

:constraints prend des expressions régulières avec la restriction que les ancres regexp ne peuvent pas être utilisées. Par exemple, la route suivante ne fonctionnera pas :

get '/:id', to: 'articles#show', constraints: { id: /^\d/ }

Cependant, notez que vous n'avez pas besoin d'utiliser des ancres car toutes les routes sont ancrées au début et à la fin.

Par exemple, les routes suivantes permettraient aux articles avec des valeurs to_param comme 1-hello-world qui commencent toujours par un nombre et aux utilisateurs avec des valeurs to_param comme david qui ne commencent jamais par un nombre de partager l'espace de noms racine :

get '/:id', to: 'articles#show', constraints: { id: /\d.+/ }
get '/:username', to: 'users#show'

3.9 Contraintes basées sur la requête

Vous pouvez également contraindre une route en fonction de n'importe quelle méthode de l'objet Request qui renvoie une String.

Vous spécifiez une contrainte basée sur la requête de la même manière que vous spécifiez une contrainte de segment :

get 'photos', to: 'photos#index', constraints: { subdomain: 'admin' }

Vous pouvez également spécifier des contraintes en utilisant un bloc constraints :

namespace :admin do
  constraints subdomain: 'admin' do
    resources :photos
  end
end

REMARQUE : Les contraintes de requête fonctionnent en appelant une méthode sur l'objet Request avec le même nom que la clé du hash, puis en comparant la valeur de retour avec la valeur du hash. Par conséquent, les valeurs de contrainte doivent correspondre au type de retour de la méthode correspondante de l'objet Request. Par exemple : constraints: { subdomain: 'api' } correspondra à un sous-domaine api comme prévu. Cependant, l'utilisation d'un symbole constraints: { subdomain: :api } ne le fera pas, car request.subdomain renvoie 'api' en tant que chaîne de caractères.

REMARQUE : Il y a une exception pour la contrainte format : bien qu'il s'agisse d'une méthode de l'objet Request, c'est également un paramètre facultatif implicite sur chaque chemin. Les contraintes de segment ont la priorité et la contrainte format n'est appliquée que lorsqu'elle est imposée par le biais d'un hash. Par exemple, get 'foo', constraints: { format: 'json' } correspondra à GET /foo car le format est facultatif par défaut. Cependant, vous pouvez utiliser un lambda comme dans get 'foo', constraints: lambda { |req| req.format == :json } et la route ne correspondra qu'aux requêtes JSON explicites.

3.10 Contraintes avancées

Si vous avez une contrainte plus avancée, vous pouvez fournir un objet qui répond à matches? que Rails devrait utiliser. Disons que vous voulez router tous les utilisateurs d'une liste restreinte vers le RestrictedListController. Vous pouvez faire :

class RestrictedListConstraint
  def initialize
    @ips = RestrictedList.retrieve_ips
  end

  def matches?(request)
    @ips.include?(request.remote_ip)
  end
end

Rails.application.routes.draw do
  get '*path', to: 'restricted_list#index',
    constraints: RestrictedListConstraint.new
end

Vous pouvez également spécifier des contraintes en tant que lambda :

Rails.application.routes.draw do
  get '*path', to: 'restricted_list#index',
    constraints: lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }
end

La méthode matches? et le lambda reçoivent tous deux l'objet request en argument.

3.10.1 Contraintes sous forme de bloc

Vous pouvez spécifier des contraintes sous forme de bloc. C'est utile lorsque vous devez appliquer la même règle à plusieurs routes. Par exemple :

class RestrictedListConstraint
  # ...Same as the example above
end

Rails.application.routes.draw do
  constraints(RestrictedListConstraint.new) do
    get '*path', to: 'restricted_list#index'
    get '*other-path', to: 'other_restricted_list#index'
  end
end

Vous pouvez également utiliser un lambda :

Rails.application.routes.draw do
  constraints(lambda { |request| RestrictedList.retrieve_ips.include?(request.remote_ip) }) do
    get '*path', to: 'restricted_list#index'
    get '*other-path', to: 'other_restricted_list#index'
  end
end

3.11 Globbing de route et segments génériques

Le globbing de route est une façon de spécifier qu'un paramètre particulier doit correspondre à toutes les parties restantes d'une route. Par exemple :

get 'photos/*other', to: 'photos#unknown'

Cette route correspondrait à photos/12 ou /photos/long/path/to/12, en définissant params[:other] sur "12" ou "long/path/to/12". Les segments préfixés par une étoile sont appelés "segments génériques".

Les segments génériques peuvent apparaître n'importe où dans une route. Par exemple :

get 'books/*section/:title', to: 'books#show'

correspondrait à books/some/section/last-words-a-memoir avec params[:section] égal à 'some/section', et params[:title] égal à 'last-words-a-memoir'.

Techniquement, une route peut avoir plus d'un segment générique. Le matcher attribue les segments aux paramètres de manière intuitive. Par exemple :

get '*a/foo/*b', to: 'test#index'
correspondrait à zoo/woo/foo/bar/baz avec params[:a] égal à 'zoo/woo', et params[:b] égal à 'bar/baz'.

En demandant '/foo/bar.json', vos params[:pages] seront égaux à 'foo/bar' avec le format de requête JSON. Si vous souhaitez retrouver le comportement ancien de la version 3.0.x, vous pouvez fournir format: false comme ceci:

get '*pages', to: 'pages#show', format: false

Si vous souhaitez rendre le segment de format obligatoire, de sorte qu'il ne puisse pas être omis, vous pouvez fournir format: true comme ceci:

get '*pages', to: 'pages#show', format: true

3.12 Redirection

Vous pouvez rediriger n'importe quel chemin vers un autre chemin en utilisant l'aide redirect dans votre routeur:

get '/stories', to: redirect('/articles')

Vous pouvez également réutiliser des segments dynamiques de la correspondance dans le chemin de redirection:

get '/stories/:name', to: redirect('/articles/%{name}')

Vous pouvez également fournir un bloc à redirect, qui reçoit les paramètres de chemin symbolisés et l'objet de requête:

get '/stories/:name', to: redirect { |path_params, req| "/articles/#{path_params[:name].pluralize}" }
get '/stories', to: redirect { |path_params, req| "/articles/#{req.subdomain}" }

Veuillez noter que la redirection par défaut est une redirection 301 "Moved Permanently". Gardez à l'esprit que certains navigateurs Web ou serveurs proxy peuvent mettre en cache ce type de redirection, rendant l'ancienne page inaccessible. Vous pouvez utiliser l'option :status pour changer le statut de la réponse:

get '/stories/:name', to: redirect('/articles/%{name}', status: 302)

Dans tous ces cas, si vous ne fournissez pas l'hôte principal (http://www.example.com), Rails prendra ces détails à partir de la requête actuelle.

3.13 Routage vers des applications Rack

Au lieu d'une chaîne de caractères comme 'articles#index', qui correspond à l'action index dans le contrôleur ArticlesController, vous pouvez spécifier n'importe quelle application Rack comme point final pour un matcher:

match '/application.js', to: MyRackApp, via: :all

Tant que MyRackApp répond à call et renvoie un [status, headers, body], le routeur ne fera pas la différence entre l'application Rack et une action. C'est une utilisation appropriée de via: :all, car vous voudrez permettre à votre application Rack de gérer tous les verbes comme elle le juge approprié.

Pour les curieux, 'articles#index' se développe en réalité en ArticlesController.action(:index), qui renvoie une application Rack valide.

Étant donné que les procédures/lambdas sont des objets qui répondent à call, vous pouvez implémenter des routes très simples (par exemple, pour les vérifications de santé) en ligne:
get '/health', to: ->(env) { [204, {}, ['']] }

Si vous spécifiez une application Rack comme point final pour un matcher, rappelez-vous que la route ne sera pas modifiée dans l'application de réception. Avec la route suivante, votre application Rack devrait s'attendre à ce que la route soit /admin:

match '/admin', to: AdminApp, via: :all

Si vous préférez que votre application Rack reçoive les requêtes à la racine au lieu de cela, utilisez mount:

mount AdminApp, at: '/admin'

3.14 Utilisation de root

Vous pouvez spécifier vers quoi Rails doit router '/' avec la méthode root:

root to: 'pages#main'
root 'pages#main' # raccourci pour le précédent

Vous devez placer la route root en haut du fichier, car c'est la route la plus populaire et elle doit être vérifiée en premier.

La route root ne route que les requêtes GET vers l'action.

Vous pouvez également utiliser root à l'intérieur des espaces de noms et des scopes. Par exemple:

namespace :admin do
  root to: "admin#index"
end

root to: "home#index"

3.15 Routes de caractères Unicode

Vous pouvez spécifier directement des routes de caractères Unicode. Par exemple:

get 'こんにちは', to: 'welcome#index'

3.16 Routes directes

Vous pouvez créer des helpers d'URL personnalisés directement en appelant direct. Par exemple:

direct :homepage do
  "https://rubyonrails.org"
end

# >> homepage_url
# => "https://rubyonrails.org"

La valeur de retour du bloc doit être un argument valide pour la méthode url_for. Ainsi, vous pouvez passer une URL sous forme de chaîne valide, un Hash, un Array, une instance Active Model ou une classe Active Model.

direct :commentable do |model|
  [ model, anchor: model.dom_id ]
end

direct :main do
  { controller: 'pages', action: 'index', subdomain: 'www' }
end

3.17 Utilisation de resolve

La méthode resolve permet de personnaliser la correspondance polymorphe des modèles. Par exemple:

resource :basket

resolve("Basket") { [:basket] }
<%= form_with model: @basket do |form| %>
  <!-- formulaire de panier -->
<% end %>

Cela générera l'URL singulière /basket au lieu de l'URL habituelle /baskets/:id.

4 Personnalisation des routes de ressources

Bien que les routes et les helpers par défaut générés par resources vous conviennent généralement, vous voudrez peut-être les personnaliser d'une manière ou d'une autre. Rails vous permet de personnaliser pratiquement n'importe quelle partie générique des helpers de ressources.

4.1 Spécifier un contrôleur à utiliser

L'option :controller vous permet de spécifier explicitement un contrôleur à utiliser pour la ressource. Par exemple :

resources :photos, controller: 'images'

reconnaîtra les chemins entrants commençant par /photos mais routera vers le contrôleur Images :

Verbe HTTP Chemin Contrôleur#Action Aide pour le nom de la route
GET /photos images#index photos_path
GET /photos/new images#new new_photo_path
POST /photos images#create photos_path
GET /photos/:id images#show photo_path(:id)
GET /photos/:id/edit images#edit edit_photo_path(:id)
PATCH/PUT /photos/:id images#update photo_path(:id)
DELETE /photos/:id images#destroy photo_path(:id)

NOTE : Utilisez photos_path, new_photo_path, etc. pour générer des chemins pour cette ressource.

Pour les contrôleurs avec un espace de noms, vous pouvez utiliser la notation de répertoire. Par exemple :

resources :user_permissions, controller: 'admin/user_permissions'

Cela routera vers le contrôleur Admin::UserPermissions.

NOTE : Seule la notation de répertoire est prise en charge. Spécifier le contrôleur avec la notation de constante Ruby (par exemple controller: 'Admin::UserPermissions') peut entraîner des problèmes de routage et générer un avertissement.

4.2 Spécifier des contraintes

Vous pouvez utiliser l'option :constraints pour spécifier un format requis sur l'id implicite. Par exemple :

resources :photos, constraints: { id: /[A-Z][A-Z][0-9]+/ }

Cette déclaration contraint le paramètre :id à correspondre à l'expression régulière fournie. Ainsi, dans ce cas, le routeur ne correspondrait plus à /photos/1 à cette route. Au lieu de cela, /photos/RR27 correspondrait.

Vous pouvez spécifier une seule contrainte à appliquer à plusieurs routes en utilisant la forme de bloc :

constraints(id: /[A-Z][A-Z][0-9]+/) do
  resources :photos
  resources :accounts
end

NOTE : Bien sûr, vous pouvez utiliser les contraintes plus avancées disponibles dans les routes non ressources dans ce contexte.

CONSEIL : Par défaut, le paramètre :id n'accepte pas les points - cela est dû au fait que le point est utilisé comme séparateur pour les routes formatées. Si vous avez besoin d'utiliser un point dans un :id, ajoutez une contrainte qui annule cela - par exemple, id: /[^\/]+/ permet tout sauf une barre oblique.

4.3 Remplacement des aides pour les routes nommées

L'option :as vous permet de remplacer la dénomination normale des aides pour les routes nommées. Par exemple :

resources :photos, as: 'images'

reconnaîtra les chemins entrants commençant par /photos et routera les requêtes vers PhotosController, mais utilisera la valeur de l'option :as pour nommer les aides.

Verbe HTTP Chemin Contrôleur#Action Aide pour le nom de la route
GET /photos photos#index images_path
GET /photos/new photos#new new_image_path
POST /photos photos#create images_path
GET /photos/:id photos#show image_path(:id)
GET /photos/:id/edit photos#edit edit_image_path(:id)
PATCH/PUT /photos/:id photos#update image_path(:id)
DELETE /photos/:id photos#destroy image_path(:id)

4.4 Remplacement des segments new et edit

L'option :path_names vous permet de remplacer les segments new et edit générés automatiquement dans les chemins :

resources :photos, path_names: { new: 'make', edit: 'change' }

Cela ferait en sorte que le routage reconnaisse des chemins tels que :

/photos/make
/photos/1/change

NOTE : Les noms d'action réels ne sont pas modifiés par cette option. Les deux chemins indiqués routeraient toujours vers les actions new et edit.

CONSEIL : Si vous souhaitez changer cette option uniformément pour toutes vos routes, vous pouvez utiliser une portée, comme ci-dessous :

scope path_names: { new: 'make' } do
  # reste de vos routes
end

4.5 Préfixer les aides pour les routes nommées

Vous pouvez utiliser l'option :as pour préfixer les aides pour les routes nommées que Rails génère pour une route. Utilisez cette option pour éviter les collisions de noms entre les routes utilisant une portée de chemin. Par exemple :

scope 'admin' do
  resources :photos, as: 'admin_photos'
end

resources :photos

Cela modifie les aides de route pour /admin/photos de photos_path, new_photos_path, etc. en admin_photos_path, new_admin_photo_path, etc. Sans l'ajout de as: 'admin_photos sur les resources de portée, les resources :photos non portées n'auront aucune aide de route.

Pour préfixer un groupe d'aides de route, utilisez :as avec scope :

scope 'admin', as: 'admin' do
  resources :photos, :accounts
end

resources :photos, :accounts

Comme précédemment, cela modifie les aides de ressources avec la portée /admin en admin_photos_path et admin_accounts_path, et permet aux ressources non portées d'utiliser photos_path et accounts_path. REMARQUE: L'espace de noms namespace ajoutera automatiquement les préfixes :as, :module et :path.

4.5.1 Espaces de noms paramétriques

Vous pouvez préfixer les routes avec un paramètre nommé:

scope ':account_id', as: 'account', constraints: { account_id: /\d+/ } do
  resources :articles
end

Cela vous fournira des chemins tels que /1/articles/9 et vous permettra de faire référence à la partie account_id du chemin en tant que params[:account_id] dans les contrôleurs, les helpers et les vues.

Cela générera également des helpers de chemin et d'URL préfixés par account_, dans lesquels vous pouvez passer vos objets comme prévu:

account_article_path(@account, @article) # => /1/article/9
url_for([@account, @article])            # => /1/article/9
form_with(model: [@account, @article])   # => <form action="/1/article/9" ...>

Nous utilisons une contrainte pour limiter la portée afin de ne correspondre qu'à des chaînes ressemblant à des identifiants. Vous pouvez modifier la contrainte selon vos besoins ou l'omettre complètement. L'option :as n'est pas strictement requise, mais sans elle, Rails générera une erreur lors de l'évaluation de url_for([@account, @article]) ou d'autres helpers qui dépendent de url_for, tels que form_with.

4.6 Restriction des routes créées

Par défaut, Rails crée des routes pour les sept actions par défaut (index, show, new, create, edit, update et destroy) pour chaque route RESTful de votre application. Vous pouvez utiliser les options :only et :except pour affiner ce comportement. L'option :only indique à Rails de créer uniquement les routes spécifiées:

resources :photos, only: [:index, :show]

Maintenant, une requête GET vers /photos réussira, mais une requête POST vers /photos (qui serait normalement routée vers l'action create) échouera.

L'option :except spécifie une route ou une liste de routes que Rails ne doit pas créer:

resources :photos, except: :destroy

Dans ce cas, Rails créera toutes les routes normales sauf la route pour destroy (une requête DELETE vers /photos/:id).

CONSEIL: Si votre application comporte de nombreuses routes RESTful, utiliser :only et :except pour générer uniquement les routes dont vous avez réellement besoin peut réduire l'utilisation de la mémoire et accélérer le processus de routage.

4.7 Chemins traduits

En utilisant scope, nous pouvons modifier les noms de chemin générés par resources:

scope(path_names: { new: 'neu', edit: 'bearbeiten' }) do
  resources :categories, path: 'kategorien'
end

Rails crée maintenant des routes vers le CategoriesController.

Verbe HTTP Chemin Contrôleur#Action Helper de route nommé
GET /kategorien categories#index categories_path
GET /kategorien/neu categories#new new_category_path
POST /kategorien categories#create categories_path
GET /kategorien/:id categories#show category_path(:id)
GET /kategorien/:id/bearbeiten categories#edit edit_category_path(:id)
PATCH/PUT /kategorien/:id categories#update category_path(:id)
DELETE /kategorien/:id categories#destroy category_path(:id)

4.8 Remplacement de la forme singulière

Si vous souhaitez remplacer la forme singulière d'une ressource, vous devez ajouter des règles supplémentaires à l'inflecteur via inflections:

ActiveSupport::Inflector.inflections do |inflect|
  inflect.irregular 'tooth', 'teeth'
end

4.9 Utilisation de :as dans les ressources imbriquées

L'option :as remplace le nom généré automatiquement pour la ressource dans les helpers de route imbriqués. Par exemple:

resources :magazines do
  resources :ads, as: 'periodical_ads'
end

Cela créera des helpers de routage tels que magazine_periodical_ads_url et edit_magazine_periodical_ad_path.

4.10 Remplacement des paramètres nommés de la route

L'option :param remplace l'identifiant de ressource par défaut :id (nom du segment dynamique utilisé pour générer les routes). Vous pouvez accéder à ce segment depuis votre contrôleur en utilisant params[<:param>].

resources :videos, param: :identifier
    videos GET  /videos(.:format)                  videos#index
           POST /videos(.:format)                  videos#create
 new_video GET  /videos/new(.:format)              videos#new
edit_video GET  /videos/:identifier/edit(.:format) videos#edit
Video.find_by(identifier: params[:identifier])

Vous pouvez remplacer ActiveRecord::Base#to_param du modèle associé pour construire une URL:

class Video < ApplicationRecord
  def to_param
    identifier
  end
end
video = Video.find_by(identifier: "Roman-Holiday")
edit_video_path(video) # => "/videos/Roman-Holiday/edit"

5 Diviser un fichier de routes très volumineux en plusieurs fichiers plus petits

Si vous travaillez dans une grande application avec des milliers de routes, un seul fichier config/routes.rb peut devenir encombrant et difficile à lire.

Rails offre un moyen de diviser un énorme fichier de routes unique en plusieurs fichiers plus petits en utilisant la macro draw.

Vous pouvez avoir un fichier de route admin.rb qui contient toutes les routes de la zone d'administration, un autre fichier api.rb pour les ressources liées à l'API, etc.

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  draw(:admin) # Chargera un autre fichier de route situé dans `config/routes/admin.rb`
end
# config/routes/admin.rb

namespace :admin do
  resources :comments
end

Appeler draw(:admin) à l'intérieur du bloc Rails.application.routes.draw tentera de charger un fichier de route qui a le même nom que l'argument donné (admin.rb dans cet exemple). Le fichier doit être situé à l'intérieur du répertoire config/routes ou de tout sous-répertoire (par exemple config/routes/admin.rb ou config/routes/external/admin.rb).

Vous pouvez utiliser le DSL de routage normal à l'intérieur du fichier de routage admin.rb, mais vous ne devez pas l'entourer du bloc Rails.application.routes.draw comme vous l'avez fait dans le fichier principal config/routes.rb.

5.1 N'utilisez pas cette fonctionnalité à moins que vous en ayez vraiment besoin

Avoir plusieurs fichiers de routage rend la découverte et la compréhension plus difficiles. Pour la plupart des applications - même celles avec quelques centaines de routes - il est plus facile pour les développeurs d'avoir un seul fichier de routage. Le DSL de routage de Rails offre déjà un moyen de diviser les routes de manière organisée avec namespace et scope.

6 Inspection et test des routes

Rails offre des fonctionnalités pour inspecter et tester vos routes.

6.1 Liste des routes existantes

Pour obtenir une liste complète des routes disponibles dans votre application, visitez http://localhost:3000/rails/info/routes dans votre navigateur pendant que votre serveur est en cours d'exécution dans l'environnement development. Vous pouvez également exécuter la commande bin/rails routes dans votre terminal pour produire la même sortie.

Les deux méthodes afficheront toutes vos routes, dans le même ordre qu'elles apparaissent dans config/routes.rb. Pour chaque route, vous verrez :

  • Le nom de la route (s'il y en a un)
  • La méthode HTTP utilisée (si la route ne répond pas à toutes les méthodes)
  • Le modèle d'URL à correspondre
  • Les paramètres de routage pour la route

Par exemple, voici une petite section de la sortie bin/rails routes pour une route RESTful :

    users GET    /users(.:format)          users#index
          POST   /users(.:format)          users#create
 new_user GET    /users/new(.:format)      users#new
edit_user GET    /users/:id/edit(.:format) users#edit

Vous pouvez également utiliser l'option --expanded pour activer le mode de formatage de tableau étendu.

$ bin/rails routes --expanded

--[ Route 1 ]----------------------------------------------------
Prefix            | users
Verb              | GET
URI               | /users(.:format)
Controller#Action | users#index
--[ Route 2 ]----------------------------------------------------
Prefix            |
Verb              | POST
URI               | /users(.:format)
Controller#Action | users#create
--[ Route 3 ]----------------------------------------------------
Prefix            | new_user
Verb              | GET
URI               | /users/new(.:format)
Controller#Action | users#new
--[ Route 4 ]----------------------------------------------------
Prefix            | edit_user
Verb              | GET
URI               | /users/:id/edit(.:format)
Controller#Action | users#edit

Vous pouvez rechercher vos routes avec l'option grep: -g. Cela affiche toutes les routes qui correspondent partiellement au nom de la méthode d'aide URL, à la méthode HTTP ou au chemin URL.

$ bin/rails routes -g new_comment
$ bin/rails routes -g POST
$ bin/rails routes -g admin

Si vous voulez seulement voir les routes qui sont mappées vers un contrôleur spécifique, il y a l'option -c.

$ bin/rails routes -c users
$ bin/rails routes -c admin/users
$ bin/rails routes -c Comments
$ bin/rails routes -c Articles::CommentsController

CONSEIL : Vous constaterez que la sortie de bin/rails routes est beaucoup plus lisible si vous élargissez votre fenêtre de terminal jusqu'à ce que les lignes de sortie ne se chevauchent pas.

6.2 Test des routes

Les routes doivent être incluses dans votre stratégie de test (tout comme le reste de votre application). Rails offre trois assertions intégrées conçues pour faciliter le test des routes :

6.2.1 L'assertion assert_generates

assert_generates affirme qu'un ensemble particulier d'options génère un chemin particulier et peut être utilisé avec des routes par défaut ou des routes personnalisées. Par exemple :

assert_generates '/photos/1', { controller: 'photos', action: 'show', id: '1' }
assert_generates '/about', controller: 'pages', action: 'about'

6.2.2 L'assertion assert_recognizes

assert_recognizes est l'inverse de assert_generates. Elle affirme qu'un chemin donné est reconnu et le route vers un endroit particulier de votre application. Par exemple :

assert_recognizes({ controller: 'photos', action: 'show', id: '1' }, '/photos/1')

Vous pouvez fournir un argument :method pour spécifier la méthode HTTP :

assert_recognizes({ controller: 'photos', action: 'create' }, { path: 'photos', method: :post })

6.2.3 L'assertion assert_routing

L'assertion assert_routing vérifie la route dans les deux sens : elle teste que le chemin génère les options, et que les options génèrent le chemin. Ainsi, elle combine les fonctions de assert_generates et assert_recognizes :

assert_routing({ path: 'photos', method: :post }, { controller: 'photos', action: 'create' })

Retour d'information

Vous êtes encouragé à contribuer à l'amélioration de la qualité de ce guide.

Veuillez contribuer si vous trouvez des fautes de frappe ou des erreurs factuelles. Pour commencer, vous pouvez lire notre contribution à la documentation section.

Vous pouvez également trouver du contenu incomplet ou des informations qui ne sont pas à jour. Veuillez ajouter toute documentation manquante pour la version principale. Assurez-vous de vérifier Edge Guides d'abord pour vérifier si les problèmes ont déjà été résolus ou non sur la branche principale. Consultez les Directives des guides Ruby on Rails pour le style et les conventions.

Si pour une raison quelconque vous repérez quelque chose à corriger mais ne pouvez pas le faire vous-même, veuillez ouvrir un problème.

Et enfin, toute discussion concernant la documentation de Ruby on Rails est la bienvenue sur le Forum officiel de Ruby on Rails.