Rutas y recursos

Convenciones básicas de enrutamiento

Echemos un vistazo a nuestras rutas tal como están ahora, utilizando rake routes:

$ rake routes Prefix Verb URI Pattern Controller#Action list_posts GET /list_posts(.:format) application#list_posts GET /show_post/:id(.:format) application#show_post new_post GET /new_post(.:format) application#new_post create_post POST /create_post(.:format) application#create_post GET /edit_post/:id(.:format) application#edit_post POST /update_post/:id(.:format) application#update_post POST /delete_post/:id(.:format) application#delete_post POST /create_comment_for_post/:post_id(.:format) application#create_comment POST /list_posts/:post_id/delete_comment/:comment_id(.:format) application#delete_comment list_comments GET /list_comments(.:format) application#list_comments 

Una de las ideas clave para las convenciones de Rails es que las aplicaciones centradas en datos (o aplicaciones crudas) tienden a tener formas muy similares para permitir que los usuarios interactúen con la aplicación, que son:

  • una página para ver una lista de algo
  • ver algo
  • mostrar un formulario para crear una nueva instancia de algo
  • crear realmente algo
  • mostrar un formulario para editar una instancia de algo
  • actualizar realmente algo
  • eliminar algo

Esos siete «patrones de interacción» son tan comunes que Rails proporciona un conjunto sólido de convenciones, desde enrutamiento a controladores, vistas y formularios, para ayudar a simplificar esos flujos de trabajo. Vamos a centrarnos en la parte de enrutamiento ahora.

Para el enrutamiento, la convención es que en lugar de tener que idear los patrones de URL, Rails recomienda que estructuremos las URL y las acciones del controlador correspondientes de la siguiente manera:

Flujo de trabajo VERBO HTTP RUTA Acción del controlador
Mostrar una lista de publicaciones OBTENER / publicaciones índice de publicaciones
Mostrar una publicación OBTENER /publicaciones/:id posts#show
Mostrar la página para crear post GET /posts/nuevo posts#nuevo
Crear un puesto de POST /posts posts#crear
Mostrar la página a editar un post GET /posts/:id/editar posts#editar
Actualización de un post PONER/PATCH /posts/:id posts#actualización
Borrar un post ELIMINAR /posts/:id mensajes # destruir

Podemos cambiar la parte post de nuestro enrutamiento actual para seguir esta convención:

# posts GET /list_posts -> GET /posts posts#index GET /show_post/:id -> GET /posts/:id posts#show GET /new_post -> GET /posts/new posts#new POST /create_post -> POST /posts posts#create GET /edit_post/:id -> GET /posts/:id/edit posts#edit POST /update_post/:id -> PUT/PATCH /posts/:id posts#update POST /delete_post/:id -> DELETE /posts/:id posts#destroy 

Y en el archivo routes.rb ,

Rails.application.routes.draw do ### posts ### get '/posts' => 'posts#index' get '/posts/new' => 'posts#new' get '/posts/:id' => 'posts#show' post '/posts' => 'posts#create' get '/posts/:id/edit' => 'posts#edit' patch '/posts/:id' => 'posts#update' put '/posts/:id' => 'posts#update' delete '/posts/:id' => 'posts#destroy' # comments later.. ... end 

Observe que con este nuevo patrón, hay muchos menos verbos en la propia URL, pero confiamos en los verbos HTTP(GET/POST/PUT/PATCH/DELETE) para proporcionar la semántica para los mismos patrones de URL, por ejemplo /posts/:id.

Tenga en cuenta que PUT se había utilizado para actualizar recursos hasta hace poco, cuando PATCH se determinó que era una mejor coincidencia semántica para esta acción. Desde entonces, Rails se ha movido a preferir PATCH, pero permitiendo ambos verbos para actualizaciones.

Otro cambio que veremos más adelante es que enrutaremos todas las URL relacionadas con publicaciones a PostsController en lugar de manejar todo en ApplicationController. Los nombres de acción de PostController

  • nuevo
  • índice
  • mostrar
  • crear
  • editar
  • actualizar
  • destruir

también son convenciones correspondientes a la interacción 7 patrones.

Este es el conjunto de convenciones más sólido que Rails le impone como desarrollador de aplicaciones. Le pediremos que haga un esfuerzo para memorizarlo. Revisaremos esto muchas veces a lo largo del libro para ayudarlo a hacer eso también.

Enrutamiento para Múltiples Recursos

A menudo necesitamos tener múltiples recursos presentes en la URL. Por ejemplo, para nuestra aplicación de blog, siempre que necesitemos tener una ruta para crear un comentario, es muy importante que sepamos en qué publicación se crea este comentario.

actualmente estamos haciendo esto:

post 'create_comment_for_post/:post_id' => 'application#create_comment' 

La convención Rails de una URL con múltiples recursos asociados es comenzar con el recurso » conteniendo «hasta el recurso» más interno». Por ejemplo, nuestras rutas para comentarios cambiarían a:

post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' get '/comments' => 'comments#index' 

La semántica de esas URL representa: «Crear un comentario en una publicación específica» y «eliminar un comentario en una publicación específica». La última ruta, «mostrar todos los comentarios en el sistema», no necesita estar» delimitada «bajo una publicación, por lo que la URL no tiene que aparecer con»/posts».

Si necesitamos tener múltiples recursos en la URL con sus ID, la convención es tal que el último recurso usará el marcador de posición :id y todo el resto será :resource_id, como :post_id.

Restful

REST significa «Transferencia de Estado de representación». Es un estilo de arquitectura de software y una guía para crear servicios web escalables. REST, como una forma de estructurar las aplicaciones web, tiene muchas facetas, pero veamos cómo se aplica a la interfaz que usamos para interactuar con las aplicaciones web, las URL.

Para ver cómo REST simplifica la semántica de las URL, veamos un ejemplo. Digamos que estamos construyendo un servicio de pedidos de pizza en línea. Una implementación ingenua de las interfaces del servicio (URLs) sería:

/check_order?order_id=2 /place_new_order /pizza_details?type=1 /pay_for_my_order?order_id=12 /cancel_order?order_id=3 /expedite_order?order_id=13 

Un diseño de interfaz reparador se vería así:

GET /orders/2 POST /orders GET /pizzas/1 POST /orders/12/payments DELETE /orders/3 POST /orders/13/expeditions 

Puede ver que las interfaces RESTful se centran en «sustantivos» o «recursos», eliminando «verbos» de las interfaces, pero confiando en los verbos HTTP estandarizados(GET/POST/PUT/DELETE) proporcionar semántica de CRUD para las acciones. Verbos como check, place, cancel se asignan directamente a verbos HTTP de GET para recuperar, POST para crear y DELETE para destruir el recurso order. pay y expedite se estructuran como creación (HTTP POST) de sub recursos de payments y expeditions en recursos orders.

Interfaces RESTful patrones de interacción de aplicaciones web estandarizados para que sean más fáciles de entender y de programar. Debido a que las interfaces se centran en la manipulación de recursos, las respuestas son mucho más predecibles. Una analogía de cómo el patrón de arquitectura RESTful simplifica la interacción con los servicios web sería cómo la base de datos Relacional y el lenguaje SQL simplifican el almacenamiento de datos. Antes de la Base de datos Relacional y SQL, los datos se almacenaban normalmente en sistemas propietarios con una lógica específica para interactuar con ellos, lo que significaba que en cada proyecto tendría que aprender un conjunto diferente de instrucciones para interactuar con los datos. Las bases de datos relacionales y SQL dieron una estructura de datos común (registros de datos como filas y columnas almacenadas en tablas) y un conjunto de interfaces comunes: cuatro verbos simples de SELECT, INSERT, UPDATE y DELETE que puede admitir todo tipo de aplicaciones.

La adopción de una interfaz RESTful para su aplicación web también optimizará su aplicación para alinearla con la forma en que se almacenan los datos del backend en las bases de datos, y facilita el desarrollo. Lo veremos en los siguientes capítulos.

Notación de recursos

Hemos hablado sobre las convenciones de enrutamiento de Rails y los patrones de URL RESTful. Ahora nuestro archivo routes.rb se vería como el siguiente:

### config/routes.rb ### Rails.application.routes.draw do ### posts ### get '/posts' => 'posts#index' get '/posts/new' => 'posts#new' get '/posts/:id' => 'posts#show' post '/posts' => 'posts#create' get '/posts/:id/edit' => 'posts#edit' patch '/posts/:id' => 'posts#update' put '/posts/:id' => 'posts#update' delete '/posts/:id' => 'posts#destroy' ### comments ### get '/comments' => 'comments#index' post '/posts/:id/comments' => 'comments#create' delete '/posts/:post_id/comments/:id' => 'comments#destroy' end 

De hecho, las rutas como las que tenemos en la sección posts son muy comunes, por lo que Rails proporciona una notación resources especial que ayuda a generarlas para usted.

Podemos simplemente hacer:

resources :posts 

Esta línea generará automáticamente las 8 líneas que teníamos antes. Tenga en cuenta que para la acción update, Rails permite verbos PUT y PATCH, por razones de compatibilidad.

Puede ejecutar bundle exec rake routes en su entorno de línea de comandos para verificar que genera exactamente el mismo conjunto de rutas.

Tenga en cuenta que esta sola línea generará 8 rutas. En nuestro caso, necesitamos todas las rutas aquí, pero si solo necesita un subconjunto de las rutas, puede definirlas de manera más explícita como:

resources :posts, only: 

Esta línea de arriba solo generaría 3 rutas para usted: escriba bundle exec rake routes para comprobarlo.

Recursos anidados

Rails también nos permite anidar recursos para crear patrones de URL con múltiples recursos, consulte a continuación:

### config/routes.rb ### Rails.application.routes.draw do resources :posts do resources :comments, only: end resources :comments, only: :index end 

Ejecute bundle exec rake routes y vea la salida, debería ser la misma que teníamos antes.

Ayudantes de ruta

Cuando ejecute bundle exec rake routes, observe la columna Prefix para algunas de estas rutas. Estos están aquí para ayudarnos a saber cómo usar los ayudantes de caminos proporcionados por Rails para nuestras rutas. Podemos usar estos prefijos seguidos de _path en nuestros controladores y vistas para construir rutas fácilmente.

Por ejemplo:

posts_path # => '/posts' post_id = 123 post_comments_path(post_id) # => '/posts/123/comments' 

¿Cuál es la ventaja de usar ayudantes de URL, en lugar de codificar las rutas como /posts/123/comments directamente en su código? (por ejemplo, en la acción del controlador?) La razón por la que desea usar ayudantes de ruta es que si desea cambiar los patrones de URL en su aplicación, es mucho más fácil usar los ayudantes de URL para devolver una ruta diferente , veamos un ejemplo:

get '/register', to: 'users#new', as: 'register' 

Cuando agregamos la cláusula » as » a esta ruta, si ejecuta bundle exec rake routes, verá la columna Prefix con register, y puede usar register_path para obtener /register la ruta. Ahora, si queremos cambiar la ruta a /login, todo lo que tenemos que hacer es:

get '/login', to: 'users#new', as: 'register' 

Ahora nuestro register_path nos da /login. No tenemos que cambiar nuestro código en la aplicación Rails en absoluto.

Más convenciones de enrutamiento

Antes de continuar, echemos un vistazo rápido a un par de variaciones de lo que ya hemos visto, así como algunas otras características disponibles para nosotros en el enrutamiento de Rails:

### config/routes.rb ### Rails.application.routes.draw do # pointing our homepage (root path) to posts#index root to: 'posts#index' # `match` & `via:` allow us to define one route and use several HTTP verbs # `as:` lets us define the name of the route prefix match '/authors/:id' => 'authors#update', via: , as: :update_author # update_author PUT|PATCH /authors/:id(.:format) authors#update resources :posts do # define extra params to pass for requests to a route get 'popular', on: :collection, action: :index, popular: true # popular_posts GET /posts/popular(.:format) posts#index {:popular=>true} get 'preview', on: :member # ... end # we can even use routes to redirect get '/home', to: redirect('/') end 

Vamos a desglosar todas las características enumeradas anteriormente de una en una.

  • root: root se usa para especificar qué acción se asigna a «/ » (la URL de nivel superior de nuestro sitio que no tiene ruta).La URL raíz de su sitio web/aplicación es la más utilizada, debido a esto root debe especificarse en la parte superior del archivo de rutas.

  • partido + vía: match se usa para hacer coincidir patrones de URL con una o más rutas. También podemos especificar qué verbo HTTP se puede usar para emparejar con una URL con este patrón. Hacemos esto pasando un hash al método match. La clave para este hash es via, y el valor es una matriz de verbos HTTP. match es una forma de propósito más general de algunos métodos de enrutamiento HTTP más utilizados, como get, post y delete. Puede tomar todas las mismas opciones que esos métodos, pero, en comparación con esos métodos, da un poco más de flexibilidad.
    Por ejemplo, al usar match podemos especificar una URL que coincida con dos rutas diferentes, cada una correspondiente a dos verbos HTTP diferentes. Normalmente, hacer esto requeriría dos comandos, en lugar de uno. Podemos ver esto en nuestro ejemplo anterior, donde coincidimos el patrón de URL '/authors/:id' con la acción 'authors#update'. Luego especificamos qué verbos HTTP se pueden usar para emitir la solicitud de esa URL con via: . Especifique siempre un método HTTP cuando use match, no hacerlo puede tener implicaciones negativas en la seguridad de su aplicación.
    match presenta otra opción para enrutar a ciertas acciones en Rails. En general, es mejor seguir los métodos HttpHelpers más utilizados, como get y post.

  • as: Mencionamos un poco antes que la opción as: se puede usar con nuestra declaración de ruta para cambiar el prefijo de nuestros ayudantes de URL. Esto se puede usar de varias maneras. Podemos usar as: para que nuestros ayudantes de URL coincidan mejor con las URL personalizadas. Otro uso es cambiar el ayudante de ruta de URL actual por algo más intuitivo o algo que coincida mejor con los recursos de una aplicación.

  • ruta de recolección: Vea cómo anidamos nuestra ruta /popular en el recurso posts. Luego usamos on: :collection para especificar en qué parte de un recurso anidamos esta ruta. Tenemos muchos posts por lo que se considera una colección. Al especificar on: :collection estamos diciendo, » Haga coincidir una URL con la ruta /posts/popular.»Si no agregamos on: :collection, Rails asumirá que esta ruta corresponde a otro recurso asociado a un solo miembro de nuestra colección de publicaciones. En ese caso, nuestra ruta se convertiría en /posts/:id/popular. También podemos especificar varias rutas de colección utilizando un formato de bloque.

collection do get 'popular' end 
  • pasar un parámetro adicional: Podemos especificar un parámetro predeterminado que siempre se pasa con nuestro hash params cuando coincidimos con ciertas URL. Hay dos formas de especificar esto; una es la misma forma en que lo hacemos anteriormente:
get 'popular', on: :collection, action: :index, popular: true 

popular: true se pasará a nuestra acción con la que coincida la ruta popular a través del hash params. Tendrá una clave de :popular y un valor de true. También podemos usar una sintaxis más explícita pasando un hash a nuestro método de ruta get, donde la clave es defaults: y el valor es otro hash que contiene el nombre del parámetro que queremos pasar a nuestra acción.

get 'popular', on: :collection, action: :index, defaults: { popular: true} 
  • ruta de miembro: Podemos usar on: member para especificar que nuestra ruta coincide con un miembro de una colección. Si usamos esto, el segmento dinámico se mostrará como :id. También se creará un ayudante de URL como preview_post. Al especificar esta ruta con on: member, le estamos diciendo a Rails que este es un miembro de este recurso en particular. Que no es solo otro recurso anidado en posts, sino más estrechamente vinculado o relacionado con nuestros posts en esta aplicación. Se pueden definir varias rutas de miembros utilizando un formato de bloque; este formato utiliza la misma sintaxis que el formato de bloque para definir varias rutas de colección, simplemente reemplace collection por member.

  • redirección: Hay otro concepto del que hablar que se muestra en nuestro ejemplo anterior, y es la redirección. Rails nos da la capacidad de redirigir de una ruta a otra mediante el uso de un ayudante de redirección junto con una ruta.get '/home', to: redirect('/'). Si alguien intenta acceder a la ruta /home, se redireccionará inmediatamente a la ruta raíz /. Esto no está restringido a una sola ruta de URL, por supuesto; también podríamos tener algo como esto: get '/home', to: redirect('/travel').

Revisión

Las rutas de rails se colocan en la parte delantera de una aplicación. Una ruta interpreta una solicitud HTTP entrante y:

  • hace coincidir una solicitud con una acción del controlador basada en la combinación de un verbo HTTP y el patrón de URL de solicitud
  • captura datos en la URL que estará disponible en params en acciones del controlador
  • Rails alienta a los desarrolladores a usar patrones de URL REST al configurar rutas, con conceptualización de la manipulación de recursos con verbos HTTP.
  • Puede usar la macro resources para generar rutas RESTful muy rápidamente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.