NO LEAS ESTE ARCHIVO EN GITHUB, LAS GUÍAS SE PUBLICAN EN https://guides.rubyonrails.org.

Rutas de Rails desde el Exterior hacia el Interior

Esta guía cubre las características de las rutas de Rails orientadas al usuario.

Después de leer esta guía, sabrás:


1 El Propósito del Router de Rails

El router de Rails reconoce URLs y las envía a la acción de un controlador, o a una aplicación Rack. También puede generar rutas y URLs, evitando la necesidad de codificar cadenas en tus vistas.

1.1 Conectando URLs al Código

Cuando tu aplicación Rails recibe una solicitud entrante para:

GET /patients/17

le pide al router que la empareje con una acción del controlador. Si la primera ruta coincidente es:

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

la solicitud se envía a la acción show del controlador patients con { id: '17' } en params.

NOTA: Rails usa snake_case para los nombres de los controladores aquí, si tienes un controlador de varias palabras como MonsterTrucksController, querrás usar monster_trucks#show por ejemplo.

1.2 Generando Rutas y URLs desde el Código

También puedes generar rutas y URLs. Si la ruta anterior se modifica para ser:

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

y tu aplicación contiene este código en el controlador:

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

y esto en la vista correspondiente:

<%= link_to 'Patient Record', patient_path(@patient) %>

entonces el router generará la ruta /patients/17. Esto reduce la fragilidad de tu vista y hace que tu código sea más fácil de entender. Ten en cuenta que el id no necesita ser especificado en el helper de la ruta.

1.3 Configurando el Router de Rails

Las rutas para tu aplicación o motor viven en el archivo config/routes.rb y típicamente se ven así:

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

Dado que este es un archivo fuente Ruby regular, puedes usar todas sus características para ayudarte a definir tus rutas, pero ten cuidado con los nombres de las variables ya que pueden chocar con los métodos DSL del router.

NOTA: El bloque Rails.application.routes.draw do ... end que envuelve tus definiciones de ruta es necesario para establecer el alcance del DSL del router y no debe ser eliminado.

2 Rutas de Recursos: el Predeterminado de Rails

Las rutas de recursos te permiten declarar rápidamente todas las rutas comunes para un controlador de recursos dado. Una sola llamada a resources puede declarar todas las rutas necesarias para tus acciones index, show, new, edit, create, update y destroy.

2.1 Recursos en la Web

Los navegadores solicitan páginas de Rails haciendo una solicitud para una URL usando un método HTTP específico, como GET, POST, PATCH, PUT y DELETE. Cada método es una solicitud para realizar una operación en el recurso. Una ruta de recurso mapea una serie de solicitudes relacionadas a acciones en un solo controlador.

Cuando tu aplicación Rails recibe una solicitud entrante para:

DELETE /photos/17

le pide al router que la mapee a una acción del controlador. Si la primera ruta coincidente es:

resources :photos

Rails enviaría esa solicitud a la acción destroy en el controlador photos con { id: '17' } en params.

2.2 CRUD, Verbos y Acciones

En Rails, una ruta de recurso proporciona un mapeo entre verbos HTTP y URLs a acciones del controlador. Por convención, cada acción también se mapea a una operación CRUD específica en una base de datos. Una sola entrada en el archivo de rutas, como:

resources :photos

crea siete rutas diferentes en tu aplicación, todas mapeando al controlador Photos:

Verbo HTTP Ruta Controlador#Acción Usado para
GET /photos photos#index mostrar una lista de todas las fotos
GET /photos/new photos#new devolver un formulario HTML para crear una nueva foto
POST /photos photos#create crear una nueva foto
GET /photos/:id photos#show mostrar una foto específica
GET /photos/:id/edit photos#edit devolver un formulario HTML para editar una foto
PATCH/PUT /photos/:id photos#update actualizar una foto específica
DELETE /photos/:id photos#destroy eliminar una foto específica

NOTA: Debido a que el router usa el verbo HTTP y la URL para emparejar solicitudes entrantes, cuatro URLs se mapean a siete acciones diferentes.

NOTA: Las rutas de Rails se emparejan en el orden en que se especifican, por lo que si tienes un resources :photos encima de un get 'photos/poll', la ruta de la acción show para la línea resources se emparejará antes que la línea get. Para solucionar esto, mueve la línea get encima de la línea resources para que se empareje primero.

2.3 Helpers de Ruta y URL

Crear una ruta de recurso también expondrá una serie de helpers a los controladores en tu aplicación. En el caso de resources :photos:

  • photos_path devuelve /photos
  • new_photo_path devuelve /photos/new
  • edit_photo_path(:id) devuelve /photos/:id/edit (por ejemplo, edit_photo_path(10) devuelve /photos/10/edit)
  • photo_path(:id) devuelve /photos/:id (por ejemplo, photo_path(10) devuelve /photos/10)

Cada uno de estos helpers tiene un helper _url correspondiente (como photos_url) que devuelve la misma ruta con el prefijo del host, puerto y prefijo de ruta actuales.

CONSEJO: Para encontrar los nombres de los helpers de ruta para tus rutas, consulta Listado de rutas existentes a continuación.

2.4 Definiendo Múltiples Recursos al Mismo Tiempo

Si necesitas crear rutas para más de un recurso, puedes ahorrar un poco de escritura definiéndolos todos con una sola llamada a resources:

resources :photos, :books, :videos

Esto funciona exactamente igual que:

resources :photos
resources :books
resources :videos

2.5 Recursos Singulares

A veces, tienes un recurso que los clientes siempre buscan sin hacer referencia a un ID. Por ejemplo, te gustaría que /profile siempre muestre el perfil del usuario actualmente conectado. En este caso, puedes usar un recurso singular para mapear /profile (en lugar de /profile/:id) a la acción show:

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

Pasar una String a to: esperará un formato controller#action. Al usar un Symbol, la opción to: debe ser reemplazada con action:. Al usar una String sin un #, la opción to: debe ser reemplazada con controller::

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

Esta ruta de recurso:

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

crea seis rutas diferentes en tu aplicación, todas mapeando al controlador Geocoders:

Verbo HTTP Ruta Controlador#Acción Usado para
GET /geocoder/new geocoders#new devolver un formulario HTML para crear el geocoder
POST /geocoder geocoders#create crear el nuevo geocoder
GET /geocoder geocoders#show mostrar el único recurso geocoder
GET /geocoder/edit geocoders#edit devolver un formulario HTML para editar el geocoder
PATCH/PUT /geocoder geocoders#update actualizar el único recurso geocoder
DELETE /geocoder geocoders#destroy eliminar el recurso geocoder

NOTA: Debido a que podrías querer usar el mismo controlador para una ruta singular (/account) y una ruta plural (/accounts/45), los recursos singulares se mapean a controladores plurales. Así que, por ejemplo, resource :photo y resources :photos crean tanto rutas singulares como plurales que se mapean al mismo controlador (PhotosController).

Una ruta de recurso singular genera estos helpers:

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

NOTA: La llamada a resolve es necesaria para convertir instancias del Geocoder a rutas a través de identificación de registro.

Al igual que con los recursos plurales, los mismos helpers que terminan en _url también incluirán el host, puerto y prefijo de ruta.

2.6 Nombres de Controladores y Rutas

Es posible que desees organizar grupos de controladores bajo un namespace. Más comúnmente, podrías agrupar varios controladores administrativos bajo un namespace Admin::, y colocar estos controladores bajo el directorio app/controllers/admin. Puedes enrutar a tal grupo usando un bloque namespace:

namespace :admin do
  resources :articles, :comments
end

Esto creará una serie de rutas para cada uno de los controladores articles y comments. Para Admin::ArticlesController, Rails creará:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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 en cambio quieres enrutar /articles (sin el prefijo /admin) a Admin::ArticlesController, puedes especificar el módulo con un bloque scope:

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

Esto también se puede hacer para una sola ruta:

resources :articles, module: 'admin'

Si en cambio quieres enrutar /admin/articles a ArticlesController (sin el prefijo de módulo Admin::), puedes especificar la ruta con un bloque scope:

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

Esto también se puede hacer para una sola ruta:

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

En ambos casos, los helpers de ruta nombrados permanecen iguales como si no hubieras usado scope. En el último caso, las siguientes rutas se mapean a ArticlesController:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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)

CONSEJO: Si necesitas usar un namespace de controlador diferente dentro de un bloque namespace, puedes especificar una ruta de controlador absoluta, por ejemplo: get '/foo', to: '/foo#index'.

2.7 Recursos Anidados

Es común tener recursos que son lógicamente hijos de otros recursos. Por ejemplo, supongamos que tu aplicación incluye estos modelos:

class Magazine < ApplicationRecord
  has_many :ads
end

class Ad < ApplicationRecord
  belongs_to :magazine
end

Las rutas anidadas te permiten capturar esta relación en tu enrutamiento. En este caso, podrías incluir esta declaración de ruta:

resources :magazines do
  resources :ads
end

Además de las rutas para revistas, esta declaración también enviará anuncios a un AdsController. Las URLs de anuncios requieren una revista:

Verbo HTTP Ruta Controlador#Acción Usado para
GET /magazines/:magazine_id/ads ads#index mostrar una lista de todos los anuncios para una revista específica
GET /magazines/:magazine_id/ads/new ads#new devolver un formulario HTML para crear un nuevo anuncio para una revista específica
POST /magazines/:magazine_id/ads ads#create crear un nuevo anuncio para una revista específica
GET /magazines/:magazine_id/ads/:id ads#show mostrar un anuncio específico para una revista específica
GET /magazines/:magazine_id/ads/:id/edit ads#edit devolver un formulario HTML para editar un anuncio para una revista específica
PATCH/PUT /magazines/:magazine_id/ads/:id ads#update actualizar un anuncio específico para una revista específica
DELETE /magazines/:magazine_id/ads/:id ads#destroy eliminar un anuncio específico para una revista específica

Esto también creará helpers de ruta como magazine_ads_url y edit_magazine_ad_path. Estos helpers toman una instancia de Magazine como el primer parámetro (magazine_ads_url(@magazine)).

2.7.1 Límites de Anidación

Puedes anidar recursos dentro de otros recursos anidados si lo deseas. Por ejemplo:

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

Los recursos anidados profundamente rápidamente se vuelven engorrosos. En este caso, por ejemplo, la aplicación reconocería rutas como:

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

El helper de ruta correspondiente sería publisher_magazine_photo_url, requiriendo que especifiques objetos en los tres niveles. De hecho, esta situación es lo suficientemente confusa como para que un artículo popular de Jamis Buck proponga una regla empírica para un buen diseño en Rails:

CONSEJO: Los recursos nunca deben anidarse más de 1 nivel de profundidad.

2.7.2 Anidación Superficial

Una forma de evitar la anidación profunda (como se recomienda arriba) es generar las acciones de colección bajo el ámbito del padre, para obtener una idea de la jerarquía, pero no anidar las acciones de miembro. En otras palabras, construir rutas solo con la cantidad mínima de información para identificar de manera única el recurso, así:

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

Esta idea encuentra un equilibrio entre rutas descriptivas y anidación profunda. Existe una sintaxis abreviada para lograr precisamente eso, a través de la opción :shallow:

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

Esto generará exactamente las mismas rutas que el primer ejemplo. También puedes especificar la opción :shallow en el recurso padre, en cuyo caso todos los recursos anidados serán superficiales:

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

El recurso articles aquí tendrá las siguientes rutas generadas para él:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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

El método shallow del DSL crea un ámbito dentro del cual cada anidación es superficial. Esto genera las mismas rutas que el ejemplo anterior:

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

Existen dos opciones para scope para personalizar las rutas superficiales. :shallow_path prefija las rutas de miembro con el parámetro especificado:

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

El recurso comments aquí tendrá las siguientes rutas generadas para él:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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

La opción :shallow_prefix agrega el parámetro especificado a los helpers de ruta nombrados:

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

El recurso comments aquí tendrá las siguientes rutas generadas para él:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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 Preocupaciones de Enrutamiento

Las preocupaciones de enrutamiento te permiten declarar rutas comunes que pueden ser reutilizadas dentro de otros recursos y rutas. Para definir una preocupación, usa un bloque concern:

concern :commentable do
  resources :comments
end

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

Estas preocupaciones pueden ser usadas en recursos para evitar la duplicación de código y compartir comportamiento a través de rutas:

resources :messages, concerns: :commentable

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

Lo anterior es equivalente a:

resources :messages do
  resources :comments
end

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

También puedes usarlas en cualquier lugar llamando a concerns. Por ejemplo, en un bloque scope o namespace:

namespace :articles do
  concerns :commentable
end

2.9 Creando Rutas y URLs desde Objetos

Además de usar los helpers de enrutamiento, Rails también puede crear rutas y URLs desde un array de parámetros. Por ejemplo, supongamos que tienes este conjunto de rutas:

resources :magazines do
  resources :ads
end

Al usar magazine_ad_path, puedes pasar instancias de Magazine y Ad en lugar de los IDs numéricos:

<%= link_to 'Ad details', magazine_ad_path(@magazine, @ad) %>

También puedes usar url_for con un conjunto de objetos, y Rails determinará automáticamente qué ruta deseas:

<%= link_to 'Ad details', url_for([@magazine, @ad]) %>

En este caso, Rails verá que @magazine es una Magazine y @ad es un Ad y, por lo tanto, usará el helper magazine_ad_path. En helpers como link_to, puedes especificar solo el objeto en lugar de la llamada completa a url_for:

<%= link_to 'Ad details', [@magazine, @ad] %>

Si quisieras enlazar solo a una revista:

<%= link_to 'Magazine details', @magazine %>

Para otras acciones, solo necesitas insertar el nombre de la acción como el primer elemento del array:

<%= link_to 'Edit Ad', [:edit, @magazine, @ad] %>

Esto te permite tratar instancias de tus modelos como URLs, y es una ventaja clave de usar el estilo de recurso.

2.10 Agregando Más Acciones RESTful

No estás limitado a las siete rutas que el enrutamiento RESTful crea por defecto. Si lo deseas, puedes agregar rutas adicionales que se apliquen a la colección o a miembros individuales de la colección.

2.10.1 Agregando Rutas de Miembro

Para agregar una ruta de miembro, solo agrega un bloque member dentro del bloque de recursos:

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

Esto reconocerá /photos/1/preview con GET, y enrutará a la acción preview del PhotosController, con el valor de ID del recurso pasado en params[:id]. También creará los helpers preview_photo_url y preview_photo_path.

Dentro del bloque de rutas de miembro, cada nombre de ruta especifica el verbo HTTP que será reconocido. Puedes usar get, patch, put, post, o delete aquí. Si no tienes múltiples rutas de member, también puedes pasar :on a una ruta, eliminando el bloque:

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

Puedes omitir la opción :on, esto creará la misma ruta de miembro, excepto que el valor de ID del recurso estará disponible en params[:photo_id] en lugar de params[:id]. Los helpers de ruta también se renombrarán de preview_photo_url y preview_photo_path a photo_preview_url y photo_preview_path.

2.10.2 Agregando Rutas de Colección

Para agregar una ruta a la colección, usa un bloque collection:

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

Esto permitirá a Rails reconocer rutas como /photos/search con GET, y enrutará a la acción search del PhotosController. También creará los helpers de ruta search_photos_url y search_photos_path.

Al igual que con las rutas de miembro, puedes pasar :on a una ruta:

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

NOTA: Si estás definiendo rutas de recursos adicionales con un símbolo como el primer argumento posicional, ten en cuenta que no es equivalente a usar una cadena. Los símbolos infieren acciones del controlador mientras que las cadenas infieren rutas.

2.10.3 Agregando Rutas para Acciones Nuevas Adicionales

Para agregar una acción nueva alternativa usando el atajo :on:

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

Esto permitirá a Rails reconocer rutas como /comments/new/preview con GET, y enrutará a la acción preview del CommentsController. También creará los helpers de ruta preview_new_comment_url y preview_new_comment_path.

CONSEJO: Si te encuentras agregando muchas acciones adicionales a una ruta de recurso, es momento de detenerte y preguntarte si estás disfrazando la presencia de otro recurso.

3 Rutas No-Resursivas

Además del enrutamiento de recursos, Rails tiene un soporte poderoso para enrutar URLs arbitrarias a acciones. Aquí, no obtienes grupos de rutas generadas automáticamente por el enrutamiento de recursos. En cambio, configuras cada ruta por separado dentro de tu aplicación.

Si bien generalmente deberías usar el enrutamiento de recursos, todavía hay muchos lugares donde el enrutamiento más simple es más apropiado. No hay necesidad de intentar encajar hasta el último pedazo de tu aplicación en un marco de recursos si no es una buena opción.

En particular, el enrutamiento simple hace que sea muy fácil mapear URLs heredadas a nuevas acciones de Rails.

3.1 Parámetros Vinculados

Cuando configuras una ruta regular, proporcionas una serie de símbolos que Rails mapea a partes de una solicitud HTTP entrante. Por ejemplo, considera esta ruta:

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

Si una solicitud entrante de /photos/1 es procesada por esta ruta (porque no ha coincidido con ninguna ruta anterior en el archivo), el resultado será invocar la acción display del PhotosController, y hacer que el parámetro final "1" esté disponible como params[:id]. Esta ruta también enrutará la solicitud entrante de /photos al PhotosController#display, ya que :id es un parámetro opcional, denotado por paréntesis.

3.2 Segmentos Dinámicos

Puedes configurar tantos segmentos dinámicos dentro de una ruta regular como desees. Cualquier segmento estará disponible para la acción como parte de params. Si configuras esta ruta:

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

Una ruta entrante de /photos/1/2 será enviada a la acción show del PhotosController. params[:id] será "1", y params[:user_id] será "2".

CONSEJO: Por defecto, los segmentos dinámicos no aceptan puntos - esto se debe a que el punto se usa como un separador para rutas con formato. Si necesitas usar un punto dentro de un segmento dinámico, agrega una restricción que anule esto – por ejemplo, id: /[^\/]+/ permite cualquier cosa excepto una barra.

3.3 Segmentos Estáticos

Puedes especificar segmentos estáticos al crear una ruta al no anteponer un colon a un segmento:

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

Esta ruta respondería a rutas como /photos/1/with_user/2. En este caso, params sería { controller: 'photos', action: 'show', id: '1', user_id: '2' }.

3.4 La Cadena de Consulta

Los params también incluirán cualquier parámetro de la cadena de consulta. Por ejemplo, con esta ruta:

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

Una ruta entrante de /photos/1?user_id=2 será enviada a la acción show del controlador Photos. params será { controller: 'photos', action: 'show', id: '1', user_id: '2' }.

3.5 Definiendo Valores Predeterminados

Puedes definir valores predeterminados en una ruta proporcionando un hash para la opción :defaults. Esto incluso se aplica a parámetros que no especificas como segmentos dinámicos. Por ejemplo:

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

Rails emparejaría photos/12 con la acción show del PhotosController, y establecería params[:format] en "jpg".

También puedes usar un bloque defaults para definir los valores predeterminados para múltiples elementos:

defaults format: :json do
  resources :photos
end

NOTA: No puedes anular los valores predeterminados a través de parámetros de consulta - esto es por razones de seguridad. Los únicos valores predeterminados que se pueden anular son los segmentos dinámicos a través de la sustitución en la ruta de URL.

3.6 Nombrando Rutas

Puedes especificar un nombre para cualquier ruta usando la opción :as:

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

Esto creará logout_path y logout_url como helpers de ruta nombrados en tu aplicación. Llamar a logout_path devolverá /exit

También puedes usar esto para anular métodos de enrutamiento definidos por recursos colocando rutas personalizadas antes de que se defina el recurso, así:

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

Esto definirá un método user_path que estará disponible en controladores, helpers y vistas que irán a una ruta como /bob. Dentro de la acción show del UsersController, params[:username] contendrá el nombre de usuario del usuario. Cambia :username en la definición de la ruta si no deseas que el nombre de tu parámetro sea :username.

3.7 Restricciones de Verbos HTTP

En general, deberías usar los métodos get, post, put, patch, y delete para restringir una ruta a un verbo en particular. Puedes usar el método match con la opción :via para emparejar múltiples verbos a la vez:

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

Puedes emparejar todos los verbos a una ruta en particular usando via: :all:

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

NOTA: Enrutar tanto solicitudes GET como POST a una sola acción tiene implicaciones de seguridad. En general, deberías evitar enrutar todos los verbos a una acción a menos que tengas una buena razón para hacerlo.

NOTA: GET en Rails no verificará el token CSRF. Nunca deberías escribir en la base de datos desde solicitudes GET, para más información consulta la guía de seguridad sobre contramedidas CSRF.

3.8 Restricciones de Segmentos

Puedes usar la opción :constraints para imponer un formato para un segmento dinámico:

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

Esta ruta emparejaría rutas como /photos/A12345, pero no /photos/893. Puedes expresar la misma ruta de manera más concisa de esta manera:

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

:constraints toma expresiones regulares con la restricción de que no se pueden usar anclas de regexp. Por ejemplo, la siguiente ruta no funcionará:

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

Sin embargo, ten en cuenta que no necesitas usar anclas porque todas las rutas están ancladas al inicio y al final.

Por ejemplo, las siguientes rutas permitirían articles con valores to_param como 1-hello-world que siempre comienzan con un número y users con valores to_param como david que nunca comienzan con un número para compartir el namespace raíz:

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

3.9 Restricciones Basadas en Solicitudes

También puedes restringir una ruta basada en cualquier método en el objeto Request que devuelva una String.

Especificas una restricción basada en solicitudes de la misma manera que especificas una restricción de segmento:

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

También puedes especificar restricciones usando un bloque constraints:

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

NOTA: Las restricciones de solicitud funcionan llamando a un método en el objeto Request con el mismo nombre que la clave del hash y luego comparando el valor de retorno con el valor del hash. Por lo tanto, los valores de restricción deben coincidir con el tipo de retorno del método del objeto Request correspondiente. Por ejemplo: constraints: { subdomain: 'api' } coincidirá con un subdominio api como se espera. Sin embargo, usar un símbolo constraints: { subdomain: :api } no lo hará, porque request.subdomain devuelve 'api' como una String.

NOTA: Hay una excepción para la restricción format: aunque es un método en el objeto Request, también es un parámetro opcional implícito en cada ruta. Las restricciones de segmento tienen prioridad y la restricción format solo se aplica como tal cuando se aplica a través de un hash. Por ejemplo, get 'foo', constraints: { format: 'json' } coincidirá con GET /foo porque el formato es opcional por defecto. Sin embargo, puedes usar un lambda como en get 'foo', constraints: lambda { |req| req.format == :json } y la ruta solo coincidirá con solicitudes JSON explícitas.

3.10 Restricciones Avanzadas

Si tienes una restricción más avanzada, puedes proporcionar un objeto que responda a matches? que Rails debería usar. Digamos que querías enrutar a todos los usuarios en una lista restringida al RestrictedListController. Podrías hacer:

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

También puedes especificar restricciones como un lambda:

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

Tanto el método matches? como el lambda reciben el objeto request como argumento.

3.10.1 Restricciones en Forma de Bloque

Puedes especificar restricciones en forma de bloque. Esto es útil cuando necesitas aplicar la misma regla a varias rutas. Por ejemplo:

class RestrictedListConstraint
  # ...Igual que el ejemplo anterior
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

También puedes usar 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 Rutas y Segmentos Comodín

El globbing de rutas es una forma de especificar que un parámetro particular debe coincidir con todas las partes restantes de una ruta. Por ejemplo:

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

Esta ruta coincidiría con photos/12 o /photos/long/path/to/12, estableciendo params[:other] en "12" o "long/path/to/12". Los segmentos prefijados con un asterisco se llaman "segmentos comodín".

Los segmentos comodín pueden ocurrir en cualquier lugar de una ruta. Por ejemplo:

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

coincidiría con books/some/section/last-words-a-memoir con params[:section] igual a 'some/section', y params[:title] igual a 'last-words-a-memoir'.

Técnicamente, una ruta puede tener incluso más de un segmento comodín. El emparejador asigna segmentos a parámetros de manera intuitiva. Por ejemplo:

get '*a/foo/*b', to: 'test#index'

coincidiría con zoo/woo/foo/bar/baz con params[:a] igual a 'zoo/woo', y params[:b] igual a 'bar/baz'.

NOTA: Al solicitar '/foo/bar.json', tu params[:pages] será igual a 'foo/bar' con el formato de solicitud de JSON. Si deseas el comportamiento anterior de 3.0.x de vuelta, podrías suministrar format: false así:

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

NOTA: Si deseas hacer que el segmento de formato sea obligatorio, de modo que no se pueda omitir, puedes suministrar format: true así:

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

3.12 Redirección

Puedes redirigir cualquier ruta a otra ruta usando el helper redirect en tu router:

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

También puedes reutilizar segmentos dinámicos del emparejamiento en la ruta a la que redirigir:

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

También puedes proporcionar un bloque a redirect, que recibe los parámetros de ruta simbolizados y el objeto de solicitud:

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

Ten en cuenta que la redirección predeterminada es una redirección 301 "Movido Permanentemente". Ten en cuenta que algunos navegadores web o servidores proxy almacenarán en caché este tipo de redirección, haciendo que la página antigua sea inaccesible. Puedes usar la opción :status para cambiar el estado de la respuesta:

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

En todos estos casos, si no proporcionas el host principal (http://www.example.com), Rails tomará esos detalles de la solicitud actual.

3.13 Enrutando a Aplicaciones Rack

En lugar de una cadena como 'articles#index', que corresponde a la acción index en el ArticlesController, puedes especificar cualquier aplicación Rack como el endpoint para un emparejador:

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

Siempre que MyRackApp responda a call y devuelva un [status, headers, body], el router no sabrá la diferencia entre la aplicación Rack y una acción. Este es un uso apropiado de via: :all, ya que querrás permitir que tu aplicación Rack maneje todos los verbos como lo considere apropiado.

NOTA: Para los curiosos, 'articles#index' en realidad se expande a ArticlesController.action(:index), que devuelve una aplicación Rack válida.

NOTA: Dado que los procs/lambdas son objetos que responden a call, puedes implementar rutas muy simples (por ejemplo, para verificaciones de salud) en línea:
get '/health', to: ->(env) { [204, {}, ['']] }

Si especificas una aplicación Rack como el endpoint para un emparejador, recuerda que la ruta no cambiará en la aplicación receptora. Con la siguiente ruta, tu aplicación Rack debería esperar que la ruta sea /admin:

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

Si prefieres que tu aplicación Rack reciba solicitudes en la ruta raíz en su lugar, usa mount:

mount AdminApp, at: '/admin'

3.14 Usando root

Puedes especificar a qué debería enrutar Rails '/' con el método root:

root to: 'pages#main'
root 'pages#main' # atajo para lo anterior

Deberías colocar la ruta root en la parte superior del archivo, porque es la ruta más popular y debería coincidir primero.

NOTA: La ruta root solo enruta solicitudes GET a la acción.

También puedes usar root dentro de namespaces y scopes. Por ejemplo:

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

root to: "home#index"

3.15 Rutas de Caracteres Unicode

Puedes especificar rutas de caracteres unicode directamente. Por ejemplo:

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

3.16 Rutas Directas

Puedes crear helpers de URL personalizados directamente llamando a direct. Por ejemplo:

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

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

El valor de retorno del bloque debe ser un argumento válido para el método url_for. Por lo tanto, puedes pasar una URL de cadena válida, Hash, Array, una instancia de Active Model o una clase de Active Model.

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

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

3.17 Usando resolve

El método resolve permite personalizar el mapeo polimórfico de modelos. Por ejemplo:

resource :basket

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

Esto generará la URL singular /basket en lugar de la habitual /baskets/:id.

4 Personalizando Rutas de Recursos

Si bien las rutas y helpers predeterminados generados por resources generalmente te servirán bien, es posible que desees personalizarlos de alguna manera. Rails te permite personalizar prácticamente cualquier parte genérica de los helpers de recursos.

4.1 Especificando un Controlador a Usar

La opción :controller te permite especificar explícitamente un controlador para usar con el recurso. Por ejemplo:

resources :photos, controller: 'images'

reconocerá rutas entrantes que comiencen con /photos pero enrutará al controlador Images:

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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)

NOTA: Usa photos_path, new_photo_path, etc. para generar rutas para este recurso.

Para controladores en un namespace, puedes usar la notación de directorio. Por ejemplo:

resources :user_permissions, controller: 'admin/user_permissions'

Esto enrutará al controlador Admin::UserPermissions.

NOTA: Solo se admite la notación de directorio. Especificar el controlador con la notación de constante Ruby (por ejemplo, controller: 'Admin::UserPermissions') puede llevar a problemas de enrutamiento y resulta en una advertencia.

4.2 Especificando Restricciones

Puedes usar la opción :constraints para especificar un formato requerido en el id implícito. Por ejemplo:

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

Esta declaración restringe el parámetro :id para que coincida con la expresión regular suministrada. Entonces, en este caso, el router ya no coincidiría con /photos/1 para esta ruta. En su lugar, /photos/RR27 coincidiría.

Puedes especificar una sola restricción para aplicar a varias rutas usando la forma de bloque:

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

NOTA: Por supuesto, puedes usar las restricciones más avanzadas disponibles en rutas no-resursivas en este contexto.

CONSEJO: Por defecto, el parámetro :id no acepta puntos - esto se debe a que el punto se usa como un separador para rutas con formato. Si necesitas usar un punto dentro de un :id, agrega una restricción que anule esto - por ejemplo, id: /[^\/]+/ permite cualquier cosa excepto una barra.

4.3 Anulando los Helpers de Ruta Nombrada

La opción :as te permite anular la nomenclatura normal para los helpers de ruta nombrada. Por ejemplo:

resources :photos, as: 'images'

reconocerá rutas entrantes que comiencen con /photos y enrutará las solicitudes al PhotosController, pero usará el valor de la opción :as para nombrar los helpers.

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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 Anulando los Segmentos new y edit

La opción :path_names te permite anular los segmentos new y edit generados automáticamente en las rutas:

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

Esto haría que el enrutamiento reconozca rutas como:

/photos/make
/photos/1/change

NOTA: Los nombres de acción reales no se cambian con esta opción. Las dos rutas mostradas todavía enrutarían a las acciones new y edit.

CONSEJO: Si te encuentras queriendo cambiar esta opción de manera uniforme para todas tus rutas, puedes usar un scope, como a continuación:

scope path_names: { new: 'make' } do
  # resto de tus rutas
end

4.5 Prefijando los Helpers de Ruta Nombrada

Puedes usar la opción :as para prefijar los helpers de ruta nombrada que Rails genera para una ruta. Usa esta opción para evitar colisiones de nombres entre rutas usando un scope de ruta. Por ejemplo:

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

resources :photos

Esto cambia los helpers de ruta para /admin/photos de photos_path, new_photos_path, etc. a admin_photos_path, new_admin_photo_path, etc. Sin la adición de as: 'admin_photos' en el recurso resources :photos con scope, los recursos no con scope no tendrán ningún helper de ruta.

Para prefijar un grupo de helpers de ruta, usa :as con scope:

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

resources :photos, :accounts

Al igual que antes, esto cambia los helpers de recurso con scope /admin a admin_photos_path y admin_accounts_path, y permite que los recursos sin scope usen photos_path y accounts_path.

NOTA: El scope namespace agregará automáticamente prefijos :as así como prefijos de :module y :path.

4.5.1 Scopes Paramétricos

Puedes prefijar rutas con un parámetro nombrado:

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

Esto te proporcionará rutas como /1/articles/9 y te permitirá referenciar la parte account_id de la ruta como params[:account_id] en controladores, helpers y vistas.

También generará helpers de ruta y URL prefijados con account_, en los que puedes pasar tus objetos como se espera:

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" ...>

Estamos usando una restricción para limitar el scope para que coincida solo con cadenas similares a IDs. Puedes cambiar la restricción para adaptarla a tus necesidades, o omitirla por completo. La opción :as tampoco es estrictamente necesaria, pero sin ella, Rails generará un error al evaluar url_for([@account, @article]) u otros helpers que dependen de url_for, como form_with.

4.6 Restringiendo las Rutas Creadas

Por defecto, Rails crea rutas para las siete acciones predeterminadas (index, show, new, create, edit, update y destroy) para cada ruta RESTful en tu aplicación. Puedes usar las opciones :only y :except para afinar este comportamiento. La opción :only le dice a Rails que cree solo las rutas especificadas:

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

Ahora, una solicitud GET a /photos tendría éxito, pero una solicitud POST a /photos (que normalmente se enviaría a la acción create) fallará.

La opción :except especifica una ruta o lista de rutas que Rails no debería crear:

resources :photos, except: :destroy

En este caso, Rails creará todas las rutas normales excepto la ruta para destroy (una solicitud DELETE a /photos/:id).

CONSEJO: Si tu aplicación tiene muchas rutas RESTful, usar :only y :except para generar solo las rutas que realmente necesitas puede reducir el uso de memoria y acelerar el proceso de enrutamiento.

4.7 Rutas Traducidas

Usando scope, podemos alterar los nombres de ruta generados por resources:

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

Rails ahora crea rutas para el CategoriesController.

Verbo HTTP Ruta Controlador#Acción Helper de Ruta Nombrada
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 Anulando la Forma Singular

Si deseas anular la forma singular de un recurso, debes agregar reglas adicionales al inflector a través de inflections:

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

4.9 Usando :as en Recursos Anidados

La opción :as anula el nombre generado automáticamente para el recurso en los helpers de ruta anidada. Por ejemplo:

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

Esto creará helpers de ruta como magazine_periodical_ads_url y edit_magazine_periodical_ad_path.

4.10 Anulando Parámetros de Ruta Nombrados

La opción :param anula el identificador de recurso predeterminado :id (nombre del segmento dinámico utilizado para generar las rutas). Puedes acceder a ese segmento desde tu controlador usando 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])

Puedes anular ActiveRecord::Base#to_param del modelo asociado para construir una 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 Dividiendo un Archivo de Rutas Muy Grande en Múltiples Archivos Pequeños

Si trabajas en una aplicación grande con miles de rutas, un solo archivo config/routes.rb puede volverse engorroso y difícil de leer.

Rails ofrece una forma de dividir un archivo único gigantesco de routes.rb en múltiples archivos pequeños usando la macro draw.

Podrías tener una ruta admin.rb que contenga todas las rutas para el área de administración, otro archivo api.rb para recursos relacionados con la API, etc.

# config/routes.rb

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

  draw(:admin) # Cargará otro archivo de ruta ubicado en `config/routes/admin.rb`
end
# config/routes/admin.rb

namespace :admin do
  resources :comments
end

Llamar a draw(:admin) dentro del bloque Rails.application.routes.draw intentará cargar un archivo de ruta que tenga el mismo nombre que el argumento dado (admin.rb en este ejemplo). El archivo debe estar ubicado dentro del directorio config/routes o cualquier subdirectorio (es decir, config/routes/admin.rb o config/routes/external/admin.rb).

Puedes usar el DSL de enrutamiento normal dentro del archivo de enrutamiento admin.rb, pero no deberías rodearlo con el bloque Rails.application.routes.draw como lo hiciste en el archivo principal config/routes.rb.

5.1 No Uses Esta Función a Menos que Realmente la Necesites

Tener múltiples archivos de enrutamiento hace que la descubribilidad y comprensión sean más difíciles. Para la mayoría de las aplicaciones, incluso aquellas con algunas centenas de rutas, es más fácil para los desarrolladores tener un solo archivo de enrutamiento. El DSL de enrutamiento de Rails ya ofrece una forma de organizar rutas de manera organizada con namespace y scope.

6 Inspeccionando y Probando Rutas

Rails ofrece facilidades para inspeccionar y probar tus rutas.

6.1 Listando Rutas Existentes

Para obtener una lista completa de las rutas disponibles en tu aplicación, visita http://localhost:3000/rails/info/routes en tu navegador mientras tu servidor está funcionando en el entorno de desarrollo. También puedes ejecutar el comando bin/rails routes en tu terminal para producir la misma salida.

Ambos métodos enumerarán todas tus rutas, en el mismo orden en que aparecen en config/routes.rb. Para cada ruta, verás:

  • El nombre de la ruta (si lo hay)
  • El verbo HTTP usado (si la ruta no responde a todos los verbos)
  • El patrón de URL a coincidir
  • Los parámetros de enrutamiento para la ruta

Por ejemplo, aquí hay una pequeña sección de la salida bin/rails routes para una ruta 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

También puedes usar la opción --expanded para activar el modo de formato de tabla expandida.

$ 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

Puedes buscar a través de tus rutas con la opción grep: -g. Esto genera cualquier ruta que coincida parcialmente con el nombre del método helper de URL, el verbo HTTP o la ruta URL.

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

Si solo deseas ver las rutas que mapean a un controlador específico, existe la opción -c.

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

CONSEJO: Encontrarás que la salida de bin/rails routes es mucho más legible si amplías la ventana de tu terminal hasta que las líneas de salida no se envuelvan.

6.2 Probando Rutas

Las rutas deben estar incluidas en tu estrategia de pruebas (al igual que el resto de tu aplicación). Rails ofrece tres afirmaciones integradas diseñadas para hacer que probar rutas sea más simple:

6.2.1 La Afirmación assert_generates

assert_generates afirma que un conjunto particular de opciones genera una ruta particular y puede usarse con rutas predeterminadas o rutas personalizadas. Por ejemplo:

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

6.2.2 La Afirmación assert_recognizes

assert_recognizes es el inverso de assert_generates. Afirma que una ruta dada es reconocida y la enruta a un lugar particular en tu aplicación. Por ejemplo:

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

Puedes suministrar un argumento :method para especificar el verbo HTTP:

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

6.2.3 La Afirmación assert_routing

La afirmación assert_routing verifica la ruta en ambos sentidos: prueba que la ruta genera las opciones, y que las opciones generan la ruta. Por lo tanto, combina las funciones de assert_generates y assert_recognizes:

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

Comentarios

Se te anima a ayudar a mejorar la calidad de esta guía.

Por favor contribuye si ves algún error tipográfico o errores fácticos. Para comenzar, puedes leer nuestra sección de contribuciones a la documentación.

También puedes encontrar contenido incompleto o cosas que no están actualizadas. Por favor agrega cualquier documentación faltante para main. Asegúrate de revisar Guías Edge primero para verificar si los problemas ya están resueltos o no en la rama principal. Revisa las Guías de Ruby on Rails para estilo y convenciones.

Si por alguna razón detectas algo que corregir pero no puedes hacerlo tú mismo, por favor abre un issue.

Y por último, pero no menos importante, cualquier tipo de discusión sobre la documentación de Ruby on Rails es muy bienvenida en el Foro oficial de Ruby on Rails.