Aida/Web: Tutorial

original:  http://www.lordzealon.com/articulos-tutoriales/aidaweb-tutorial/

 

Aquí os presento la traducción del tutorial sobre Aida. El original podéis encontrarlo en: http://www.aidaweb.si/tutorial.html

La traducción, obviamente, no es perfecta ni mucho menos. No soy un experto en inglés, y seguramente contenga errores. Agradecería comentarios y/o correcciones.

1. Introducción

Para comprender cómo crear aplicaciones web con Aida, y comenzar a programar las tuyas propias, aquí, se presentar un corto tutorial que te guiará a través de los pasos principales en la creación de una libreta de direcciones online.

Este tutorial está preparado para Visual Works, pero puede ser usado en Squeak y Dolphin Smalltalk (sólo las declaraciones de clase son distintas).

Primero, asegurémonos que tenemos Aida (5.6 o posterior) correctamente instalado evaluando en un WorkSpace:

SwazooAida demoStart

Entonces, abrimos un navegador apuntando a http://localhost:8888 y logueamos con usuario admin y password: password.

Ahora estamos preparados para comenzar con el modelo de Dominio.

2. Preparando el modelo de Dominio

Aida usa una separación estricta de los objetos del dominio de su representación visual al estilo MVC. Por lo que necesitamos crear algunos objetos del modelo de dominio primero. En nuestro ejemplo, haremos un modelo de dominio para nuestro ejemplo de la Libreta de Direcciones, instanciarlo y llenarlo con algunas direcciones de ejemplo.:

En un Browser, creamos el paquete AidaAdressBook. A través de la plantilla de creación de clases, creamos una, llamada ADemoAddressBook que herede de Object con la variable de instancia: direcciones
Object subclass: #ADemoAddressBook
    
instanceVariableNames: ‘direcciones’
    
classVariableNames:
    
poolDictionaries:
    
category: ‘AidaAddressBook’

Crea una nueva clase, ADemoAddress con las variables de instancia: nombre apellido telefono email
Object subclass: #ADemoAddress
    
instanceVariableNames: ‘nombre apellido telefono email’
    
classVariableNames:
    
poolDictionaries:
    
category: ‘AidaAddressBook’

Crea e inicializa metodos y accessors para la variable de instancia de ADemoAddressBook
initDirecciones
    
direcciones := OrderedCollection new.

direcciones
    
direcciones isNil ifTrue: .
    
^ addresses

Crea accessors y mutators para todas las variables de instancia de la clase ADemoAddress

Añade un método de clase para creación rápida de ADemoAddress (recuerda que debe ser de clase no de instancia. Debes presionar antes Class en el panel de la clase, antes de crear el método)
nuevoNombre: unNombre apellido: unApellido telefono: unTelefono email: unEmail
    
^super new
            
nombre: unNombre;
            apellido: unApellido;
            telefono: unTelefono;
            email: unEmail

En un workspace crea una instancia de ADemoAddressBook y rellénala con algunas direcciones de ejemplo.
|book|
book := ADemoAddressBook new.
book direcciones
    
add: (ADemoAddress
            
nuevoNombre: ‘Sebastjan’
            
apellido: ‘Dormir’
            
telefono: ‘01/514 33 66′
            
email: ’sebastjan@something.si’);
    
add: (ADemoAddress
            
nuevoNombre: ‘John’
            
apellido: ‘Newton’
            
telefono: ‘05/555 77 66′
            
email: ‘john@something.si’);
    
add: (ADemoAddress
            
nuevoNombre: ‘Elizabeth’
            
apellido: ‘Schneider’
            
telefono: ‘03/561 23 12′
            
email: ‘elizabeth@something.at’).

3. Registrando el objeto root del dominio.

Después que nuestra ADemoAddressBook está preparada, en el mismo workspace, registraremos su URL en Aida, para que sea accesible vía web. En el mismo workspace añadimos lo siguiente y después evaluamos todo:

(AIDASite named: ‘aidademo’) urlResolver defaultURL: ‘/libretadirecciones.html’ forObject: book

Necesitas registrar sólamente un objeto root para tu modelo de dominio. Los enlaces a todos los objetos desde root se crearán automáticamente.

4. Creando clases de presentación (Apps).

Para representar nuestros objetos de dominio como páginas web, necesitamos crear una clase WebApplication (presentación) para cada objeto del dominio que queramos mostrar. En nuestro caso, éstos son, ADemoAddressBook y ADemoAddress. Es muy sencillo; sólamente crea una subclase de WebApplication con un nuevo nombre de clase acorde a la formula: ‘nombre de la case’+App. En nuestro caso, necesitas dos Apps: ADemoAddressBook y AddressApp.

WebApplication subclass: #ADemoAddressBookApp
    
instanceVariableNames:
    
classVariableNames:
    
poolDictionaries:
    
category: ‘AidaAddressBook’

WebApplication subclass: #ADemoAddressApp
    
instanceVariableNames:
    
classVariableNames:
    
poolDictionaries:
    
category: ‘AidaAddressBook’

4.1 Metodos view

Comenzamos creando nuestro primer método ‘view’, que es, un método que construirá una página web para representar una de las vistas de nuestros objetos, Los métidos View, son nombrados siguiendo la fórmula: view+’Nombre de la Vista’. Por ejemplo, para la vista ’summary’ creamos un método #viewSummary. Aunque cada App debería tambien tener una vista por defecto ‘main’ y por lo tanto, un método #viewMain. Escribamos una para nuestra ADemoAddressBookApp usando el protocolo printing.

viewMain
    | e |
    e := WebElement new.
    e addTextH1: ‘Libreta de Direcciones’.
    self pageFrameWith: e title: ‘Libreta de Direcciones’

En este caso, hemos creado una instancia local de WebElement, que es una subclase de todos los otros elementos de una página web (como WebText, WebLink etc.) y un “compuesto”, por lo que podemos añadir otro WebElements a el. Podemos también hacer esto de una manera más larga, instanciando un nuevo elemento y añadiéndolo a éste, por ejemplo:

e add: (WebText text: ‘Libreta de Direcciones’ attributes: #bold)

La corta, métodos más directos pueden ser encontrados en el protocolo ‘adding’ de WebElement (añadir texto, imágenes, enlaces, formularios, componentes ajax ,etc…)

La línea de nuestro ejemplo, añade nuestro elemento en una página y lo “enmarca” con una cabecera estandar y barra de navegación a la izquierda. Prueba a cambiar esto para añadir directamente a self (self add:e)

Ahora, podemos abrir nuestra primera página en un navegador: http://localhost:8888/libretadirecciones.html

Si no lo hiciste, debes loguear como admin con password: password, de otra manera, no podrás ver la página. Como admin, tienes derecho a ver todas las páginas por defecto, mientras que como invitado no (aunque existen configuraciones de seguridad para permitirlo).

4.2. Texto

Ahora modifiquemos el método viewMain de ADemoAddressBookApp para escribir todas las direcciones.
viewMain
| e |
e := WebElement new.
e addTextH1: ‘Libreta de Direcciones’.
self observee direcciones do: .
self pageFrameWith: e title: ‘Libreta de Direcciones’
Observa el mensje self observee. De esta manera preguntamos a nuestra App retornar la referencia del objeto del dominio que representa (recuerdas el patrón observer en MVC?). El método addText: es usado para añadir texto a nuestra página, que también puede incluir etiquetas HTML. Finalmente, el método addBreak crea una nueva línea.

Pero la página se vé fea. Pongamos los datos en una tabla.

5.Tablas

Tablas en Aida, son construidas de manera conveniente, que reduce el trabajo necesario para Tablas web.
viewMain
| e |
e := WebElement new.
e addTextH1: ‘Libreta de Direcciones’.
e table border: 1.
self observee direcciones do: .
self pageFrameWith: e title: ‘Libreta de Direcciones’

Cada elemento tiene una tabla latente que es activada cuando nosotros comenzamos a usar metodos de manipulación/acceso a tablas (table, newtable, cell, new cell, row, newRow). Simplemente secuenciando estos métodos, podemos hacer cualquier cosa con tablas. Podemos incluso anidar tablas de esta manera (recuerda, una tabla es un WebElement y por ello, puede contener otra tabla).
Pongamos nobre y apellido en un tabla anidada.

e add: (WebText text: ‘Libreta de Direcciones’ attributes: #bold)

6.Hojas de estilo CSS.

Hagamos que la tabla se vea mejor. La mejor manera es usar CSS (Cascade Style Sheet) para separar el diseño del contenido. Existen ya mucho métodos de estilo incluidos en la clase WebStyle (mirar métodos css en el protocolo styles-screen). Nosotros reusaremos estilos ya definidos en el método css24webgrid para tablas. Cambiemos la línea de nuestra tabla (e table border: 1) a:

e table class: #webGrid.

Ahora, nuestra tabla tiene fondo coloreado, y la fuente más pequeña. Los métodos de estilo en WebStyle son compuestos juntos por orden alfabético en una página CSS, que puede mirarse en
http://localhost:8888/screen.css .

El orden alfabético es importante para CSS y es la razón por la que los métodos css tienen números en sus nombres para mantener el orden. Cada método que comienza con ‘css’ será incluido en nuestra declaración CSS. Podemos crear un CSS separado para impresión también, nombrando métodos como cssPrint. Para hacer tu propio estilo (skin), sólo debes subclasear WebStyle, y añadir o sobreescribir métodos css. Entonces cambia el estilo en AIDASite:

(AIDASite named: ‘test’) styleClass: ‘MyWebStyle’; style: nil

Nota: Cambiando el estilo a nil, se instanciará una nueva clase de estilo al primer uso

5. Vincular objetos
Puesto nuestros objetos del dominio son vinculados con referencias de objeto, nuestra páginas web deberían estarlo también. Por ejemplo, nuestra ADemoAddressBook mantiene referencias a todos las ADemoAddresses, y, puesto representaremos cada dirección con una página web separada, necesitamos crear un enlace URL desde ADemoAddressBook a ésta.

Primero, comenzaremos preparando una vista principal para las direcciones en ADemoAddressApp

viewMain
| e |
e := WebElement new.
e addTextH1: ‘Direcciones’.
e table class: #webGrid.
e cell addText: ‘nombre: ‘. e newCell addTextBold: self observee nombre. e newRow.
e cell addText: ‘apellido: ‘. e newCell addTextBold: self observee apellido. e newRow.
e cell addText: ‘telefono: ‘. e newCell addTextBold: self observee telefono. e newRow.
e cell addText: ‘email: ‘. e newCell addTextBold: self observee email.
self pageFrameWith: e title: ‘Direcciones’

5.URLs

A nosotros nos gustaría tener unas urls apropiadas para nuestras direcciones, algo como /address/newton.html y no automáticamente generar una, como /object/o4899057.html, que es la creada para ti por defecto por Aida. Para suferir a Aida cual es la mejor URL, implementa en tu clase del dominio el método #preferedUrl. Hacemos lo siguiente para ADemoAddress.

preferedUrl
^’/address/’, self surname, ‘.html’

El URL sugerido será aceptado si el url es único, de otra manera, será degradado a uno generado automáticamente.

Ahora, estamos preparados para hacer enlaces a nuestras direcciones.

5.Enlaces URL

Los enlaces URL se construyen automáticamente simplemente apuntando al objeto del dominio que nos gustaría mostrar. En nuestro caso, apuntaremos a cada una de las direcciones en la libreta de direcciones. Usaremos el método #addLinkTo:text: desde WebElement para cambiar en surname en un enlace, por ejemplo:

e addLinkTo: address text: address surname.

Actualizaremos nuestro viewMain en ADemoAddressBookApp:

viewMain
| e |
e := WebElement new.
e addTextH1: ‘Address book’.
e table class: #webGrid.
self observee addresses do: .
self pageFrameWith: e title: ‘Address book’

Ahora, todos los apellidos serán cambiados a enlaces. Chequea como se ven en el navegador. Nuestra sugerencia obviamente funciona. Si cliqueamos en uno de ellos podemos ver que cada dirección es mostrada como una página web tal y como escribimos en la viewMain de ADemoAddressApp.

6.Formularios

Es momento de añadir nuevas entrada en nuestra ADemoAddressBook. Para ésto, tenemos que crear un formulario, procesar los campos y añadir la nueva entrada en nuestra libreta de direcciones.

Crea un enlace en la vista principal de la libreta de direcciones.
viewMain
| e |
e := WebElement new.
e addTextH1: ‘Libreta de Direcciones’.
e table class: #webGrid.
self observee addresses do: .
e addBreak.
e addLinkTo: self text: ‘Añadir nueva entrada’ view: #add.
self pageFrameWith: e title: ‘Libreta de Direcciones’

Ahora tenemos un enlace a una vista ‘añadir’. Crea el correspondiente método (#viewAdd) en la clase ADemoAddressBookApp:

viewAdd
| e |
e := WebElement new.
newEntry := ADemoAddress new.
e addTextH1: ‘Añadir nueva entrada’.
e cell addText: ‘Nombre:’ ; addBreak.
e cell addInputFieldAspect: #nombre for: newEntry.
e newRow.
e cell addText: ‘Apellido:’ ; addBreak.
e cell addInputFieldAspect: #apellido for: newEntry.
e newRow.
e cell addText: ‘Telefono:’ ; addBreak.
e cell addInputFieldAspect: #telefono for: newEntry.
e newRow.
e cell addText: ‘Email:’ ; addBreak.
e cell addInputFieldAspect: #email for: newEntry.
e newRow.
e cell addButtonText: ‘Añadir esta entrada’.
self pageFrameWith: e title: ‘Añadir esta entrada’.

Ésto creará un formulario enlazado a la variable de instancia newEntry. Declárala en tu definición de clase. Cuando el boton ‘Añadir esta entrada’ es presionado, Aida llamará al método #actionAdd (por defecto, el botón submit de un formulario llama al metodo #nombreDeAccionDeLaVista). Echemos un vistazo.

actionAdd
self observee direcciones add: newEntry.
self redirectToView: #main.

Simple verdad? En un ejemplo del mundo real, puedes chequear y validar los datos (por ejemplo, verificar que el número de teléfono es un número válido).

Para más información sobre formularios en Aida, mira el documento: http://www.aidaweb.si/forms.html
o navega por el código fuente..

7.Mejorando la tabla

Aida, hace el scriptint javascript/Ajax realmente sencillo. No necesitas conocer Javascript, Aida lo hace por tí.
Mejoraremos nuestra tabla AdemoAddressBook añadiendo dos características: ordenar y filtrar.
Aquí está el método completo #viewMain:

viewMain
    
| e entryList |
    
e := WebElement new.
    
e addTextH1: ‘Libreta de Direccioens’.
    
entryList := WebGrid new.
    
entryList columnNames: #( ‘Nombre’ ‘Apellido’ ‘Telefono’ ‘Email’);
        
setNumbering;
        
columnFilters: #(nil true true nil nil);
        
sortOn: 2;
        
collection: self observee direcciones;
        
columnAspects: #(nil #nombre #apellido #telefono #email);
        
column: 3 addBlock: .
    
e add: entryList.
    
e addBreak.
    
e addLinkTo: self text: ‘Añadir una entrada’ view: #add.
self pageFrameWith: e title: ‘Libreta de Direcciones’

Ves la diferencia?
Creamos un objeto Webgrid y le dimos todas las informaciones que necesitaba para trabajar correctamente.

  • #columnNames: es usado para darle un nombre a cada columna.
    #setNumbering simplemente le dice al webGrid que le dé a cada línea un número (que estará en la primera columna)
    #columnFilters: le dice al webGrid en qué columna queremos usar un filtro. En este caso, solo el ‘Surname’ y ‘Name’ podrán ser filtrados
    #sortOn: Marca la columna iniciar donde ordenar.
    #collection: marca la colección que será mostrada en el Webgrid. Usaremos el#observee para recibir nuestra ADemoAddressBook.
    #columnAspects: dice qué método será llamado por cada columna en los objetos de la colección.
    #column: addBlock: La columna especificada será renderizada con el bloque dado (que debe retornar un WebElement)

Ya está. Refresca tu navegador y disfruta tu nueva mejorada tabla.