lunes, 13 de junio de 2011

Scoping de rutas en Rails 3

En sistema de rutas de Rails es el que se encarga de:
  • Identificar peticiones entrantes y redireccionarlas a una acción concreta de un controlador
  • Definir patrones que servirán para generar URLs dirigidas hacia nuestras acciones

Rails nos permite gran cantidad de opciones de configuración para definir nuestras rutas.
He pensado que puede ser útil tomar aquí nota de las principales opciones de scoping que suelen ser más utilizadas.

El método scope

El método scope nos permite aplicar configuraciones a conjuntos de rutas que compartan dichas opciones de configuración.

Por ejemplo, supongamos que queremos definir las siguientes rutas:


match 'timelords/new' => 'timelords#new'
match 'timelords/edit/:id' => 'timelords#edit'
match 'timelords/revive/:id' => 'timelords#revive'


Como vemos, las tres rutas comparten una serie de puntos en común, como son la composición de su URL (siempre entran por 'timelords/*') y el controlador al que dirigen sus peticiones (TimelordsController).

El método scope posee diversas opciones que nos permiten ahorrar código en casos como este:

Controller


scope :controller => :timelords do
match 'timelords/new' => 'new'
match 'timelords/edit/:id' => 'edit'
match 'timelords/revive/:id' => 'revive'
end


La opción controller nos permite especificar el controlador al que pertenecen las acciones a las que vamos a redirigir estas rutas. Además, con un poco de azúcar sintáctico, podemos hacer uso del método scope de una forma más simple:

scope :timelords do
...
end


E incluso más simple aún:

controller :timelords do
...
end




Path prefix

De forma análoga, si lo que queremos es definir el path que van a seguir todas nuestras rutas, podemos utilizar la opción path:

scope :path => '/timelords' do
match 'new' => 'timelords#new'
match 'edit/:id' => 'timelords#edit'
match 'revive/:id' => 'timelords#revive'
end


Para ponernos las cosas mucho más simples, de nuevo, podemos hacer:

scope '/timelords' do
match 'new' => 'timelords#new'
match 'edit/:id' => 'timelords#edit'
match 'revive/:id' => 'timelords#revive'
end


Name prefix

Podemos hacer que todos los helper que genera el sistema de rutas tengan el prefijo que queramos (por ejemplo, admin) utilizando la opción as:

scope :path => '/timelords', :as => 'original' do
match 'new' => 'timelords#new'
match 'edit/:id' => 'timelords#edit'
match 'revive/:id' => 'timelords#revive'
end


Con esto obtendremos helpers como "original_timelords_path", "edit_original_timelord_path" etc.

Module

En caso de que queramos expresar que todas nuestras acciones hacen referencia a un controlador perteneciente a un módulo concreto, usaremos la opción module:

scope :module => 'drwho' do
match 'timelords/new' => 'timelords#new'
match 'timelords/edit/:id' => 'timelords#edit'
match 'timelords/revive/:id' => 'timelords#revive'
end


En este caso, asumimos que existe un controlador DrWho::TimelordsController, al que hacen referencia todas las acciones de nuestras rutas.

Namespace

El método namespace nos permite definir de una sóla vez, las opciones :module, :as y :path, de forma que:

namespace :drwho do
match 'new' => 'timelords#new'
match 'edit/:id' => 'timelords#edit'
match 'revive/:id' => 'timelords#revive'
end


Define rutas como "drwho_timelords_path", "edit_drwho_timelord_path" etc

Nótese que namespace también tiene la opción :controller, de forma que podríamos haberla usado para definir el controlador al que hacen referencia las acciones de dicho namespace. En el ejemplo no se utiliza porque en cada ruta definimos el controlador al que pertenece la acción (a este controlador hay que añadirle el módulo que define el namespace).

Por supuesto, aunque en aquí sólo hemos definido rutas clásicas, el scoping funciona igualmente para rutas REST definidas con resources. Después de todo, resources no es más que un atajo para definir las 7  rutas REST (index, show, new, create, edit, update, destroy).


Extra: Podemos consultar en cualquier momento la ruta que nos devuelve un helper, desde la consola de rails, utilizando el objeto app:

Loading development environment (Rails 3.0.7)
ruby-1.8.7-p248 :001 > app.timelords_path



Y eso es todo por ahora.
En breve ampliaremos el tema con rutas REST y cómo se abordan en Rails :)

No hay comentarios:

Publicar un comentario