jueves, 25 de febrero de 2016

Gestión de rutas en Rails

Seguro que te has preguntado por los automatismos que Ruby on Rails tiene por todos los rincones del framework. Una de las primeras que llaman la atención son los nombres abreviados de las rutas tipo "new_user" o "edit_item". Cuando se está empezando con Rails, al poco de modificar lo que viene de serie con los scaffold, nos solemos encontrar con un batiburrillo de links con nombres de ruta como los anteriores y otros más manuales e improvisados o bien con una cadena fija o bien indicando :controller, :action, :id, etc... Vamos a intentar arrojar algo de luz a todo a la forma en que funcionan las rutas y los alias de cada una de ellas. 

Lo primero es que debemos conocer el contenido del fichero config/routes.rb. En este fichero se declaran las rutas o más bien el esquema de rutas que sigue Ruby on Rails para saber a qué método y de qué controller hay que redirigir la petición. Un error típico de una ruta no contemplada es el siguiente:
ActionController::RoutingError (No route matches [GET] "/items/0/unkownroute"):
Si miras tu config/routes.rb, un contenido típico sería del tipo:


Myrubyapp::Application.routes.draw do
    resources :items
    resources :users

    match '/users/:id/logout', :to => "users#logout" , :via => 'get', :as => 'user_logout'
    match "/users/:id/login", :to => "users#login" , :via => 'get'
    match "/users/:id/login", :to => "users#login" , :via => 'post'
    match "/users/:id/change_pass", :to => "users#change_pass"  , :via => 'post'
    
    #...

    get '/items/:id/preview', to: 'items#preview', as: 'preview_item'

    #...

    root :to => "items#index"

end
Primero lo primero 
¿ Adónde se encamina a un visitante que no sabe a donde va ? A donde indique la linea que comienza con "root". Cuando se crea una aplicación el primer controller puede que sea el destinatario de la URL root pero podemos cambiar facilmente este comportamiento editando esta linea. 

Sintaxis
Vemos 2 tipos de sintaxis: las lineas que empiezan por match y las que empiezan por "GET", "POST", etc... Son equivalentes. Sirva como ejemplo de la equivalencia el que las 2 siguientes lineas darían el mismo resultado:
match "/items/:id/preview", :to => "items#preview"  , :via => 'get', as: 'preview_item'
get '/items/:id/preview', to: 'items#preview', as: 'preview_item'

La parte mágica
Ya habrás adivinado que esos nombres mágicos ("edit_item", "new_user", etc..) los podemos crear con el atributo :as.

IMPORTANTE: el estandar HTTP
Un programador web debe ser consciente de los distintos métodos posibles de interacción entre el cliente y el servicio web. Se suele frivolizar con ello y se usa en demasía el GET para todo. Tampoco quiero ser purista aquí, aunque hay que serlo si se puede, pero qué menos que no usar GET cuando está estrictamente desaconsejado e incluso prohibido. 

Todo el mundo sabe como funcionan los buscadores. Van visitando enlaces y navagando de aquí para allá para realizar una reconstrucción de los contenidos de la web. No olvides qué usan el método "GET"!!!!. ¿ Qué pasa si pones una operación de escritura en tu sistema a tiro de GET ? Exacto, te van a bondardear y sin querer van a modificar el estado de tu sistema. El tema es importante y da para otra entrada en el blog. Me conformo de momento con que sepas que ninguna operación que suponga cambios del tipo que sea debe atender a una invocación con GET.
Me remito al fichero config/routes.rb donde verás que hay urls que se sirven indistintamente del método HTTP de invocación GET y POST
    match "/users/:id/login", :to => "users#login" , :via => 'get'
    match "/users/:id/login", :to => "users#login" , :via => 'post'
    match "/users/:id/change_pass", :to => "users#change_pass"  , :via => 'post'



otros solo para GET
get '/items/:id/preview', to: 'items#preview', as: 'preview_item'

y otro solo para POST

    match "/users/:id/change_pass", :to => "users#change_pass"  , :via => 'post'


¿ Cómo queda el resultado ?
El resultado ya te lo puedes imaginar, ¿ no ?. Ah, que no te lo imaginas. No pasa nada para eso está el comando siguiente:
$ bundle exec rake routes
          Prefix Verb   URI Pattern                                   Controller#Action
            items GET    /items(.:format)                              items#index
                  POST   /items(.:format)                              items#create
         new_item GET    /items/new(.:format)                          items#new
        edit_item GET    /items/:id/edit(.:format)                     items#edit
             item GET    /items/:id(.:format)                          items#show
                  PATCH  /items/:id(.:format)                          items#update
                  PUT    /items/:id(.:format)                          items#update
                  DELETE /items/:id(.:format)                          items#destroy
[...]

Creo que para una primera aproximación a las rutas en Rails no está mal.

No hay comentarios:

Publicar un comentario