10. Rutas controladores & vistas - williamromero/curso-rails GitHub Wiki
![]() |
Para comprender un poco sobre el funcionamiento integrado entre Nginx & Puma, a continuación poseemos un diagrama ilustrativo en el cual podremos analizar un poco la interacción de las peticiones en nuestra aplicación. Al lado izquierdo, tenemos la imagen de como funciona de forma real, una aplicación de RoR ejecutándose en un servidor web o bien, en un entorno local. Lo primero que necesitamos saber es que Puma, es un servidor basado en Rack, que es la interfaz que se ejecuta entre las peticiones URI y los frameworks web de Ruby. Es común que conozcamos Nginx como un servidor de peticiones HTTP & que Puma sea reconocido como un servidor de aplicaciones ya que interactúa entre las peticiones HTTP, la interfaz Rack & la aplicación web. |
Es así, que Puma es utilizado para respetar los principios fundamentales de separation of concerns o lo que vendría siendo en español, lo que conocemos como el principio de responsabilidad única, en el que Puma se encargará únicamente de la administración de las peticiones y nos permitirá manejar algunos métodos como: path_info, ip, request method, body, user_agent y el framework web, de la interacción con los recursos de la información.
El router de Rails, reconoce URLs y las despacha en forma de acciones de controlador o una aplicación Rack. Este enrutador también nos permite crear URLs para evitar establecer hipervínculos con texto sobre escrito. Cuando la aplicación Rails recibe una petición entrante, este pregunta al router si existe una acción de controlador que haga match con la que hemos nombrado.
Para visualizar las rutas de nuestro proyecto, podemos obtener una lista de las mismas ingresando el siguiente comando en consola:
rails routes
Prefix Verb URI Pattern Controller#Action
root GET / products#index
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:uuid/edit(.:format) products#edit
product GET /products/:uuid(.:format) products#show
PATCH /products/:uuid(.:format) products#update
PUT /products/:uuid(.:format) products#update
DELETE /products/:uuid(.:format) products#destroyPara ello, necesitaremos ir al archivo config/routes.rb e ingresar lo siguiente:
# config/routes.rb
get 'products', to: 'products#index'Y luego llamar a esta ruta desde nuestra vista. En este caso nos enviará a la ruta principal para obtener la lista de todos los registros.
# app/views/products/show.html.erb
<%= link_to 'Ir a principal', products_path %>O también podemos pedirle al controlador que ejecute una redirección cuando persistamos un registro mediante el método respond_to, que nos permite renderizar nuestra respuesta en diferentes formatos. En este caso, emplearemos el método redirect_url para enviar al usuario a la lista de productos luego de su
# app/controllers/products_controller.rb
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to product_url(@product.uuid), notice: "Product was successfully created." }
else
format.html { render :new, status: :unprocessable_entity }
end
end
endCuando vayamos creando nuevas rutas, obtendremos más y más líneas como en el siguiente ejemplo. Con ellas, nos será fácil reconocer para que sirve cada una.
| VERB | URI Pattern | Controlador/Acción | Descripción |
|---|---|---|---|
| GET | '/products/:uuid' | 'products#show | Obtenemos la acción show del controlador products |
| GET | '/products/:uuid/purchase' | 'products#purchase' | Obtenemos la acción purchase del controlador products y el parámetro :uuid del mismo. |
El único problema de esta solución manual, es que tendremos que describir todas para cada acción que necesitemos hacer. Para evitarlo, podemos hacer uso de un método muy importante llamado resources.
Los resources nos permiten crear un paquete de rutas que nos sirven para navegar entre los endpoints sobre los que manejaremos los registros de un modelo de datos de nuestra aplicación.
resources :products
root GET / products#index
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:uuid/edit(.:format) products#edit
product GET /products/:uuid(.:format) products#show
PATCH /products/:uuid(.:format) products#update
PUT /products/:uuid(.:format) products#update
DELETE /products/:uuid(.:format) products#destroyLos namespaces nos sirven para organizar un grupo de controladores dentro de módulo con un nombre determinado. Es común que los controladores se organicen en grupos de información similar, es por ello que con el identificador de módulo determinado generamos un block con el namespace y posterior a ello, seremos capaces de movilizar nuestros archivos (en el controlador y en las vistas) a un folder con ese nombre.
Por último, pero no menos importante es que la ruta también se verá afectada, puesto que para ingresar a ese recurso, estableceremos una estructura de la siguiente forma namespaces:modelo. A continuación podremos ver un ejemplo.
En el archivo de rutas:
# config/routes.rb
namespace :admin do
resources :articles, :comments
end En la consola:
mkdir app/controllers/admin
mkdir app/views/admin
mv app/controllers/articles_controller.rb app/controllers/admin/
mv app/views/articles app/views/admin/Y por último, agregamos en nuestro controlador el nombre del namespaces de la siguiente manera:
class Admin::ArticlesController < ApplicationControllerLuego, si corremos el comando rails routes obtendremos nuestras nuevas rutas de la siguiente forma:
| HTTP Verb | Path | Controller#Action | Named Route Helper |
|---|---|---|---|
| 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) |
Cuando usamos namespaces, estamos obteniendo predefinidos los valores de las opciones que podemos modificar en las rutas, que son los campos path, as y module. Estos atributos de nuestras rutas, nos permiten modificar tanto el prefijo con el que obtendremos el named route helper (que son las rutas que emplearemos dentro de las vistas de nuestro proyecto para dirigirnos de una pantalla a otra), o bien para configurar un prefijo de modulo que nos servirá para que podamos depositar diferentes tipos de vistas de datos, dentro de una carpeta en específico.
Por ejemplo:
namespace "admin" do
resources :articles
endEl siguiente snippet representa lo mismo pero usando scope:
scope "/admin", as: "admin", module: "admin" do
resources :articles
endAmbos snippets van a generar las rutas de artículos de la siguiente forma:
| HTTP Verb | Path | Controller#Action | Named Route Helper |
|---|---|---|---|
| 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) |
| VERBO | Acción |
|---|---|
| GET | Obtener un recurso |
| POST | Crear un recurso / Enviar a su creación |
| PUT | Actualizar un recurso |
| DELETE | Eliminar un recurso |
| PATCH | Actualizar un recurso de forma parcial |
| PUT VERB | PATCH VERB |
|---|---|
| PUT es un método de modificación de recursos en el que el cliente envía datos que actualizan todo el recurso. | PATCH es un método de modificación de recursos en el que el cliente envía datos parciales que se actualizarán sin modificar los datos completos. |
| En una solicitud PUT, la entidad adjunta se considera una versión modificada del recurso almacenado en el servidor de origen y el cliente solicita que se reemplace la versión almacenada. | Sin embargo, con PATCH, la entidad adjunta contiene un conjunto de instrucciones que describen cómo se debe modificar un recurso que reside actualmente en el servidor de origen para producir una nueva versión.. |
| Se dice que HTTP PUT es idempotente, por lo que si envía una solicitud de reintento varias veces, eso debería ser equivalente a una sola modificación de solicitud | HTTP PATCH básicamente se dice que no es -idempotente. Entonces, si vuelve a intentar la solicitud N veces, terminará teniendo N recursos con N URI diferentes creados en el servidor. |
| Tiene un uso alto de ancho de banda | Dado que solo los datos que deben modificarse si se envían en el cuerpo de la solicitud como carga útil, tiene un uso ancho de banda bajo . |
Referencias
Differences between _path & _url prefix
