Ruby on Rails
Enrutamiento
Buscar..
Introducción
Observaciones
En general, "enrutamiento" es cómo las URL son "manejadas" por su aplicación. En el caso de Rails, generalmente es qué controlador y qué acción de ese controlador manejará una URL entrante en particular. En las aplicaciones de Rails, las rutas generalmente se ubican en el archivo config/routes.rb
.
Enrutamiento de recursos (básico)
Las rutas se definen en config/routes.rb
. A menudo se definen como un grupo de rutas relacionadas, utilizando los resources
o resource
métodos de resource
.
resources :users
crean las siguientes siete rutas, todas UsersController
a las acciones de UsersController
:
get '/users', to: 'users#index'
post '/users', to: 'users#create'
get '/users/new', to: 'users#new'
get '/users/:id/edit', to: 'users#edit'
get '/users/:id', to: 'users#show'
patch/put '/users/:id', to: 'users#update'
delete '/users/:id', to: 'users#destroy'
Nombres de las acciones se muestran después de la #
en el to
parámetro anterior. Los métodos con esos mismos nombres se deben definir en app/controllers/users_controller.rb
siguiente manera:
class UsersController < ApplicationController
def index
end
def create
end
# continue with all the other methods…
end
Puede limitar las acciones que se generan con only
o except
:
resources :users, only: [:show]
resources :users, except: [:show, :index]
Puede ver todas las rutas de su aplicación en cualquier momento ejecutando:
$ rake routes
$ rake routes
# OR
$ rails routes
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
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
Para ver solo las rutas que se asignan a un controlador en particular:
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
$ rake routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
# OR
$ rails routes -c static_pages
static_pages_home GET /static_pages/home(.:format) static_pages#home
static_pages_help GET /static_pages/help(.:format) static_pages#help
Puedes buscar a través de rutas usando la opción -g
. Esto muestra cualquier ruta que coincida parcialmente con el nombre del método auxiliar, la ruta de la URL o el verbo HTTP:
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
$ rake routes -g new_user # Matches helper method
$ rake routes -g POST # Matches HTTP Verb POST
# OR
$ rails routes -g new_user # Matches helper method
$ rails routes -g POST # Matches HTTP Verb POST
Además, al ejecutar el servidor de rails
en modo de desarrollo, puede acceder a una página web que muestra todas sus rutas con un filtro de búsqueda, con prioridad de arriba a abajo, en <hostname>/rails/info/routes
. Se verá así:
Ayudante | Verbo HTTP | Camino | Controlador # Acción |
---|---|---|---|
Camino / Url | [Match Path] | ||
ruta_usuario | OBTENER | /users(.:format) | índice de usuarios # |
ENVIAR | /users(.:format) | usuarios # crear | |
new_user_path | OBTENER | /users/new(.:format) | usuarios # nuevo |
edit_user_path | OBTENER | /users/:id/edit(.:format) | usuarios # editar |
ruta_usuario | OBTENER | /users/:id(.:format) | usuarios # show |
PARCHE | /users/:id(.:format) | usuarios # actualizar | |
PONER | /users/:id(.:format) | usuarios # actualizar | |
BORRAR | /users/:id(.:format) | usuarios # destruir |
Las rutas se pueden declarar disponibles solo para miembros (no para colecciones) utilizando el resource
del método en lugar de los resources
en routes.rb
. Con resource
, una ruta de index
no se crea de forma predeterminada, sino solo cuando se solicita explícitamente una como esta:
resource :orders, only: [:index, :create, :show]
Restricciones
Puede filtrar qué rutas están disponibles usando restricciones.
Hay varias formas de usar restricciones, incluyendo:
Por ejemplo, una restricción basada solicitada para permitir solo una dirección IP específica para acceder a una ruta:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
Vea otros ejemplos similares ActionDispatch :: Routing :: Mapper :: Scoping .
Si desea hacer algo más complejo, puede usar restricciones más avanzadas y crear una clase para envolver la lógica:
# lib/api_version_constraint.rb
class ApiVersionConstraint
def initialize(version:, default:)
@version = version
@default = default
end
def version_header
"application/vnd.my-app.v#{@version}"
end
def matches?(request)
@default || request.headers["Accept"].include?(version_header)
end
end
# config/routes.rb
require "api_version_constraint"
Rails.application.routes.draw do
namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
resources :users # Will route to app/controllers/v1/users_controller.rb
end
namespace :v2, constraints: ApiVersionConstraint.new(version: 2) do
resources :users # Will route to app/controllers/v2/users_controller.rb
end
end
Una forma, varios botones de enviar
También puede utilizar el valor de las etiquetas de envío de un formulario como una restricción para enrutar a una acción diferente. Si tiene un formulario con varios botones de envío (por ejemplo, "vista previa" y "envío"), podría capturar esta restricción directamente en su routes.rb
, en lugar de escribir javascript para cambiar la URL de destino del formulario. Por ejemplo, con la gema commit_param_routing puede aprovechar las ventajas de rails submit_tag
submit_tag
primer parámetro de Rails submit_tag
permite cambiar el valor de su parámetro de confirmación de formulario
# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
<!-- Big form here -->
<%= submit_tag "Preview" %>
<%= submit_tag "Submit" %>
# => <input name="commit" type="submit" value="Preview" />
# => <input name="commit" type="submit" value="Submit" />
...
<% end %>
# config/routes.rb
resources :orders do
# Both routes below describe the same POST URL, but route to different actions
post 'mass_order', on: :collection, as: 'mass_order',
constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses "submit"
post 'mass_order', on: :collection,
constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user presses "preview"
# Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form url
# CommitParamRouting is just a class like ApiVersionContraint
end
Rutas de alcance
Rails te ofrece varias formas de organizar tus rutas.
Alcance por URL :
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
Esto genera las siguientes rutas.
get '/admin/dashboard', to: 'administration#dashboard'
post '/admin/employees', to: 'employees#create'
get '/admin/employees/new', to: 'employees#new'
get '/admin/employees/:id/edit', to: 'employees#edit'
get '/admin/employees/:id', to: 'employees#show'
patch/put '/admin/employees/:id', to: 'employees#update'
delete '/admin/employees/:id', to: 'employees#destroy'
Puede tener más sentido, en el lado del servidor, mantener algunas vistas en una subcarpeta diferente, para separar las vistas de administrador de las vistas de los usuarios.
Alcance por módulo
scope module: :admin do
get 'dashboard', to: 'administration#dashboard'
end
module
busca los archivos del controlador en la subcarpeta del nombre dado
get '/dashboard', to: 'admin/administration#dashboard'
Puede cambiar el nombre del prefijo de los ayudantes de ruta agregando un parámetro as
scope 'admin', as: :administration do
get 'dashboard'
end
# => administration_dashboard_path
Rails proporciona una manera conveniente de hacer todo lo anterior, utilizando el método de namespace
. Las siguientes declaraciones son equivalentes.
namespace :admin do
end
scope 'admin', module: :admin, as: :admin
Alcance por controlador
scope controller: :management do
get 'dashboard'
get 'performance'
end
Esto genera estas rutas.
get '/dashboard', to: 'management#dashboard'
get '/performance', to: 'management#performance'
Anidación poco profunda
Las rutas de recursos aceptan una opción :shallow
que ayuda a acortar las URL cuando sea posible. Los recursos no deben estar anidados a más de un nivel de profundidad. Una forma de evitar esto es mediante la creación de rutas poco profundas. El objetivo es dejar de lado los segmentos de URL de colección principal donde no son necesarios. El resultado final es que las únicas rutas anidadas generadas son para :index
:create
y :new
. El resto se mantienen en su propio contexto de URL superficial. Hay dos opciones de alcance para personalizar rutas poco profundas:
: shallow_path: Prefiere las rutas de los miembros con un parámetro específico
scope shallow_path: "sekret" do resources :articles do resources :comments, shallow: true end end
: shallow_prefix : Agrega parámetros especificados a los ayudantes nombrados
scope shallow_prefix: "sekret" do resources :articles do resources :comments, shallow: true end end
También podemos ilustrar rutas shallow
más por:
resources :auctions, shallow: true do
resources :bids do
resources :comments
end
end
codificado alternativamente de la siguiente manera (si está satisfecho con el bloque):
resources :auctions do
shallow do
resources :bids do
resources :comments
end
end
end
Las rutas resultantes son:
Prefijo | Verbo | Patrón de URI |
---|---|---|
bid_comments | OBTENER | /bids/:bid_id/comments(.:format) |
ENVIAR | /bids/:bid_id/comments(.:format) | |
new_bid_comment | OBTENER | /bids/:bid_id/comments/new(.:format) |
Editar comentario | OBTENER | /comments/:id/edit(.:format) |
comentario | OBTENER | /comments/:id(.:format) |
PARCHE | /comments/:id(.:format) | |
PONER | /comments/:id(.:format) | |
BORRAR | /comments/:id(.:format) | |
remate de ofertas | OBTENER | /auctions/:auction_id/bids(.:format) |
ENVIAR | /auctions/:auction_id/bids(.:format) | |
new_auction_bid | OBTENER | /auctions/:auction_id/bids/new(.:format) |
edit_bid | OBTENER | /bids/:id/edit(.:format) |
oferta | OBTENER | /bids/:id(.:format) |
PARCHE | /bids/:id(.:format) | |
PONER | /bids/:id(.:format) | |
BORRAR | /bids/:id(.:format) | |
subastas | OBTENER | / subastas (. formato) |
ENVIAR | / subastas (. formato) | |
nueva_aucción | OBTENER | /auctions/new(.:format) |
edición_aucción | OBTENER | /auctions/:id/edit(.:format) |
subasta | OBTENER | /auctions/:id(.:format) |
PARCHE | /auctions/:id(.:format) | |
PONER | /auctions/:id(.:format) | |
BORRAR | /auctions/:id(.:format) |
Si analiza las rutas generadas con cuidado, notará que las partes anidadas de la URL solo se incluyen cuando son necesarias para determinar qué datos mostrar.
Preocupaciones
Para evitar la repetición en rutas anidadas, las preocupaciones proporcionan una excelente manera de compartir recursos comunes que son reutilizables. Para crear una preocupación utilice el método de concern
dentro de la routes.rb
archivo. El método espera un símbolo y un bloque:
concern :commentable do
resources :comments
end
Aunque no crea ninguna ruta en sí, este código permite usar el atributo :concerns
en un recurso. El ejemplo más simple sería:
resource :page, concerns: :commentable
El recurso anidado equivalente se vería así:
resource :page do
resource :comments
end
Esto construiría, por ejemplo, las siguientes rutas:
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
Para que las preocupaciones sean significativas, debe haber múltiples recursos que utilicen la preocupación. Los recursos adicionales podrían usar cualquiera de la siguiente sintaxis para llamar a la inquietud:
resource :post, concerns: %i(commentable)
resource :blog do
concerns :commentable
end
Redireccion
Puede realizar la redirección en las rutas de Rails de la siguiente manera:
get '/stories', to: redirect('/posts')
match "/abc" => redirect("http://example.com/abc")
También puede redirigir todas las rutas desconocidas a una ruta determinada:
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
match '*path' => redirect('/')
Miembro y rutas de recogida
La definición de un bloque miembro dentro de un recurso crea una ruta que puede actuar sobre un miembro individual de esa ruta basada en recursos:
resources :posts do
member do
get 'preview'
end
end
Esto genera la siguiente ruta de miembro:
get '/posts/:id/preview', to: 'posts#preview'
# preview_post_path
Las rutas de recolección permiten crear rutas que pueden actuar sobre una colección de objetos de recursos:
resources :posts do
collection do
get 'search'
end
end
Esto genera la siguiente ruta de recolección:
get '/posts/search', to: 'posts#search'
# search_posts_path
Una sintaxis alternativa:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
URLs params con un punto
Si desea admitir un parámetro url más complejo que un número de identificación, puede tener problemas con el analizador si el valor contiene un punto. Se asumirá que todo lo que sigue a un período es un formato (es decir, json, xml).
Puede solucionar esta limitación utilizando una restricción para ampliar la entrada aceptada.
Por ejemplo, si desea hacer referencia a un registro de usuario por dirección de correo electrónico en la url:
resources :users, constraints: { id: /.*/ }
Ruta de la raíz
Puede agregar una ruta de página de inicio a su aplicación con el método root
.
# config/routes.rb
Rails.application.routes.draw do
root "application#index"
# equivalent to:
# get "/", "application#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
render "homepage"
end
end
Y en la terminal, las rake routes
( rails routes
en Rails 5) producirán:
root GET / application#index
Debido a que la página principal suele ser la ruta más importante, y las rutas se priorizan en el orden en que aparecen, la ruta root
debería ser la primera en su archivo de rutas.
Acciones adicionales de REST
resources :photos do member do get 'preview' end collection do get 'dashboard' end end
Esto crea las siguientes rutas además de las 7 rutas RESTful predeterminadas :
get '/photos/:id/preview', to: 'photos#preview'
get '/photos/dashboards', to: 'photos#dashboard'
Si desea hacer esto para líneas simples, puede usar:
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
También puede agregar una acción a la /new
ruta:
resources :photos do get 'preview', on: :new end
Que creará:
get '/photos/new/preview', to: 'photos#preview'
Tenga en cuenta al agregar acciones a sus rutas RESTful, ¡es probable que le falte otro recurso!
Ámbito local disponible
Si su aplicación está disponible en diferentes idiomas, normalmente muestra la configuración regional actual en la URL.
scope '/(:locale)', locale: /#{I18n.available_locales.join('|')}/ do
root 'example#root'
# other routes
end
Se podrá acceder a su raíz a través de las configuraciones regionales definidas en I18n.available_locales
.
Montar otra aplicación
el montaje se utiliza para montar otra aplicación (básicamente, la aplicación en bastidor) o los rieles de los motores que se utilizarán dentro de la aplicación actual
sintaxis:
mount SomeRackApp, at: "some_route"
Ahora puede acceder a la aplicación montada anteriormente usando el ayudante de ruta some_rack_app_path
o some_rack_app_url
.
Pero si desea cambiar el nombre de este ayudante, puede hacerlo como:
mount SomeRackApp, at: "some_route", as: :myapp
Esto generará los ayudantes myapp_path
y myapp_url
que se pueden usar para navegar a esta aplicación montada.
Redirecciones y rutas de comodines
Si desea proporcionar una URL por conveniencia para su usuario pero asignarla directamente a otra que ya esté usando. Utilice una redirección:
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
Bueno, eso se puso interesante rápido. El principio básico aquí es simplemente usar el método #redirect
para enviar una ruta a otra. Si su ruta es bastante simple, es un método muy sencillo. Pero si también desea enviar los parámetros originales, necesita hacer un poco de gimnasia capturando el parámetro dentro de %{here}
. Tenga en cuenta las comillas simples alrededor de todo.
En el ejemplo anterior, también hemos cambiado el nombre de la ruta por conveniencia utilizando un alias con el: como parámetro. Esto nos permite usar ese nombre en métodos como los ayudantes #_path. De nuevo, prueba tus $ rake routes
con preguntas.
Dividir rutas en múltiples archivos
Si su archivo de rutas es abrumadoramente grande, puede poner sus rutas en múltiples archivos e incluir cada uno de los archivos con el método require_relative
de Ruby:
config/routes.rb
: YourAppName::Application.routes.draw do
require_relative 'routes/admin_routes'
require_relative 'routes/sidekiq_routes'
require_relative 'routes/api_routes'
require_relative 'routes/your_app_routes'
end
config/routes/api_routes.rb
: YourAppName::Application.routes.draw do
namespace :api do
# ...
end
end
Rutas anidadas
Si desea agregar rutas anidadas, puede escribir el siguiente código en el archivo routes.rb
.
resources :admins do
resources :employees
end
Esto generará las siguientes rutas:
admin_employees GET /admins/:admin_id/employees(.:format) employees#index
POST /admins/:admin_id/employees(.:format) employees#create
new_admin_employee GET /admins/:admin_id/employees/new(.:format) employees#new
edit_admin_employee GET /admins/:admin_id/employees/:id/edit(.:format) employees#edit
admin_employee GET /admins/:admin_id/employees/:id(.:format) employees#show
PATCH /admins/:admin_id/employees/:id(.:format) employees#update
PUT /admins/:admin_id/employees/:id(.:format) employees#update
DELETE /admins/:admin_id/employees/:id(.:format) employees#destroy
admins GET /admins(.:format) admins#index
POST /admins(.:format) admins#create
new_admin GET /admins/new(.:format) admins#new
edit_admin GET /admins/:id/edit(.:format) admins#edit
admin GET /admins/:id(.:format) admins#show
PATCH /admins/:id(.:format) admins#update
PUT /admins/:id(.:format) admins#update
DELETE /admins/:id(.:format) admins#destroy