Secciones

Artículos para tus primeros pasos

Si estás empezando a introducirte en el mundo de Groovy y Grails, no te pierdas nuestros artículos básicos: 

Entrevistas con los expertos
 

Los protagonistas te cuentan de qué van los proyectos más importantes del mundo Groovy:


Un proyecto de:
ImaginaWorks
Campus Escuela de Groovy

Cómo funciona Grails WebFlow

jueves 13/09/2007

Los flujos web son conversaciones entre el servidor y el navegador que se extienden más allá de una petición http, aunque no llegan a constituir una sesión (un usuario puede ejecutar varios flujos diferentes dentro de la misma sesión). Se trata de una herramienta ideal para crear asistentes al estilo de las aplicaciones de escritorio, que vayan haciendo preguntas al usuario y guiando sus pasos en función de las respuestas.

Grails implementa esta funcionalidad desde la versión 0.6, basándose en el proyecto Spring Web Flow, pero como siempre, facilitando enormemente la tarea de crear flujos para el programador. Un flujo en Grails es una acción en la que se definen los distintos nodos o estados por los que puede pasar el usuario, y los eventos que dirigen al usuario de un nodo a otro.

Cómo crear un flujo

Para crear un flujo, simplemente añadimos a un controlador una acción cuyo nombre termine en "Flow" (recuerda: "convention over configuration"), y dentro de ella definimos los estados que forman el flujo:

class BookController {   
   def index = {
      redirect(action:'shoppingCart')
   }    
   def shoppingCartFlow = {
             ..
   }
}

Al estar definidos dentro de una única acción, todos los nodos del flujo compartirán un mismo ámbito, aunque la ejecución se reparta en diferentes peticiones http. Existirá un ámbito "flow" al que asociar variables que serán accesibles desde todos los nodos del flujo, de forma similar a como las variables del ámbito "session" están accesibles desde todos los controladores durante una sesión.

Comienzo y final de un flujo

Los flujos tienen un principio, un final y un estado. En el controlador esto se representa como nodos en la acción del flujo, por ejemplo:
class BookController {   
   ...
   def shoppingCartFlow = {
       showCart {
           on("checkout").to "enterPersonalDetails"
           on("continueShopping").to "displayCatalogue"
       }
       ...
       displayCatalogue {
            redirect(controller:"catalogue", action:"show")
       }
       displayInvoice()
   }
}

En este caso el flujo es "shoppingCart" (sin "Flow"), y el comienzo es el nodo "showCart". Además tiene dos nodos, "displayCatalogue" y "displayInvoice". Éste últimom es además el final del flujo. Como véis, en el primer nodo tenemos gestores de evento que indican a qué nodo del flujo iremos en función de la etiqueta que recibamos (luego veremos más sobre esto).

Respecto a la vista, necesitaremos una página gsp por cada estado del flujo. Los gsp asociados a este flujo deberán estar en grails-app/views/book/shoppingCart/, y llamarse como cada uno de los nodos, con extensión gsp (por ejemplo: grails-app/views/book/shoppingCart/showCart.gsp)

Eventos

Como hemos visto, al invocar la url http://<host>/<aplicacion>/shoppingCart, Grails invocará el primer nodo del flujo ("showCart"), y nos mostrará la vista correspondiente. Desde ahí podremos saltar a distintos nodos por medio de eventos, que se gestionan en el nodo. En este caso, se declaran dos eventos: "checkout" nos lleva al nodo "enterPersonalDetails", y "continueShopping" nos lleva al nodo "displayCatalogue". Los eventos pueden generarse de varias maneras:

1. Mediante formularios, usando botones submit:

<g:form action="shoppingCart">
    <g:submitButton name="continueShopping" value="Continue Shopping"></g:submitButton>               
    <g:submitButton name="checkout" value="Checkout"></g:submitButton>
</g:form>

2. Mediante enlaces, usando la etiqueta <g:link> y pasando como action el flujo, y el evento correspondiente.

<g:link action="shoppingCart" event="checkout" />

El ámbito "flow"

Como vimos al principio, con la llegada de los flujos se crea un nuevo ámbito en el que almacenar información que será visible a lo largo de varias peticiones http. Se trata del ámbito "flow", que me permite almacenar los datos relativos a un flujo para que estén disponibles desde todos los nodos. Todos los objetos almacenados en "flow" se eliminarán cuando el flujo llegue al estado final.

Veamos un ejemplo:

enterPersonalDetails {
   on("submit") {
         def p = new Person(params)
         flow.person = p
         if(!p.validate())return error()
   }.to "enterShipping"
   on("return").to "showCart"
}

El nodo "enterPersonalDetails" declara dos eventos posibles: "submit" y "return". El último simplemente nos manda de vuelta al nodo "showCart", mientras que el primero crea un objeto Person, puebla sus propiedades con los parámetros (Grails hace binding automático aquí, cada parámetro se convertirá al tipo correspondiente de la propiedad del bean que tenga el mismo nombre), y lo almacena en el ámbito "flow".

Fijaros también en que comprobamos si los valores introducidos en el formulario son válidos. El método validate() lo introduce GORM en todas las clases del modelo de datos, y comprueba que las propiedades del objeto cumplen con las restricciones definidas en la clase mediante la propiedad "constraints" (más sobre eso aquí). Si validate devuelve falso, invocamos el método predefinido error(), que nos devolverá a la vista anterior para que corrigamos los datos.

Conclusión

El objetivo de este artículo es servir de introducción a los flujos en Grails, comentando qué son y cómo se crean. Hay más que contar, pero lo dejaremos para otro artículo más adelante.

Contenidos relacionados:



0 comentarios:

Tienes que estar registrado para iniciar sesión y poder publicar tus comentarios