Ahora que ya contamos con una primera versión de nuestro modelo de datos, es hora de comenzar a desarrollar la primera página de nuestra aplicación. Esta página simplemente mostrará la lista con los mensajes más recientes, así como una lista con los anteriores mensajes.
Aquí tenemos un prototipo de lo que queremos conseguir:
Antes de desarrollar nuestra primera pantalla tenemos que hacer una cosa más. Trabajar con una aplicación web sin contar con datos de prueba es bastante arduo. Uno ni siquiera puede verificar lo que está haciendo. Pero dado que todavía no hemos desarrollado las pantallas para crear mensajes, no podemos cargar mensajes a nuestro sistema de blogs.
Una manera de cargar información de prueba en el blog es mediante un archivo de fixtures a ser cargado cuando iniciamos la aplicación. Para ello crearemos una tarea de inicio (Bootstrap Job). Una terea de Play es algo que se ejecuta a sí mismo sin depender de ninguna llamada HTTP, por ejemplo cuando la aplicación se inicia o a intervalos específicos de tiempo utilizando una tarea CRON.
Creemos la tarea /yabe/app/Bootstrap.java
la cual se encargará de cargar un conjunto de datos de prueba usando Fixtures
:
import play.*;
import play.jobs.*;
import play.test.*;
import models.*;
@OnApplicationStart
public class Bootstrap extends Job {
}
Hemos anotado esta tarea con la anotación OnApplicationStart
para indicarle a Play que queremos ejecutar esta tarea al iniciar la aplicación.
De hecho esta tarea será ejecutada de manera diferente dependiendo de que estemos en modo DEV (desarrollo) ó PROD (producción). En modo desarrollo Play espera al primer pedido HTTP para iniciar la aplicación, de forma tal que esta tarea será ejecutada sincrónicamente al recibir el primer pedido. De esa manera, si la tarea produce algún error, obtendrá el mensaje correspondiente al error en su browser. Sin embargo, en modo producción, la tarea se ejecutará al iniciar la aplicación (en el momento en que ejecutamos el comando play run
) y evitará que la aplicación se inicie en caso de detectar algún error.
Debe crear un archivo initial-data.yml
en la carpeta yabe/conf/
. Puede reutilizar los contenidos del archivo data.yml
que acabamos de usar en el paso anterior.
Ahora inicie la aplicación mediante el comando play run
y navegue a la página http://localhost:9000/.
Ahora sí podemos comenzar a desarrollar la página principal.
¿Recuerda cómo hacía Play para mostrar la página de bienvenida? En primer lugar el archivo routes
especifica que un pedido al URL /
invocará al método de acción definido en controllers.Application.index()
. Este método llama al render()
que ejecutará el template /yabe/app/views/Application/index.html
.
Mantendremos estos componentes, pero a su vez agregaremos código para cargar la lista de mensajes y mostrarlos en pantalla.
Abra el controlador /yabe/app/controllers/Application.java
y modifique la acción index()
para cargar la lista de mensajes de la siguiente manera:
package controllers;
import java.util.*;
import play.;
import play.mvc.;
import models.*;
public class Application extends Controller {
public static void index() { Post frontPost = Post.find(“order by postedAt desc”).first(); List olderPosts = Post.find( “order by postedAt desc” ).from(1).fetch(10); render(frontPost, olderPosts); }}
¿Ha notado como pasamos objetos al método render()
? Nos permitirá acceder a ellos desde el template utilizando los mismos nombres. En este caso, las variables frontPost
y olderPosts
estarán disponibles en el template.
Abra el template /yabe/app/views/Application/index.html
y modifíquelo para mostrar estos objetos:
#{extends 'main.html' /}
#{set title:'Home' /}
#{if frontPost}
#{/if}
#{else}
There is currently nothing to read here.
#{/else}
Puede aprender más acerca del funcionamiento de los templates en El motor de templates. Básicamente, le permite acceder a sus objetos de Java dinámicamente. Internamente utilizamos Groovy. La mayor parte de los prácticos comandos que ve (como el operador ?:
) vienen del lenguaje Groovy. Pero no necesita aprender Groovy para escribir templates de Play. Si ya ha trabajado con algún otro lenguaje de templates, como JSP con JSTL, no se sentirá perdido en absoluto.
Bien, ahora refresque la página principal de nuestra aplicación.
No muy atractivo… ¡pero funciona!
Sin embargo, habrá notado que ya comenzamos a duplicar código. Dado que mostraremos mensajes de muchas maneras distintas, deberíamos crear algo similar a una función que podamos llamar desde distintos templates. Esto es exactamente lo que un ‘tag’ de Play hace.
Para crear un tag, simplemente cree un archivo /yabe/app/views/tags/display.html
. Un tag no es más que otro template que acepta parámetros, como una función. El tag #{display /}
tendrá dos parámetros: el objeto Post a mostrar y el modo en que lo queremos desplegar: home
, teaser
o full
.
*{ Display a post in one of these modes: 'full', 'home' or 'teaser' }*
#{if as == ’full’}
#{list items:_post.comments, as:’comment’}
#{/if}
Ahora usando este tag podemos reescribir la página principal sin duplicar código:
#{extends 'main.html' /}
#{set title:'Home' /}
#{if frontPost}
#{display post:frontPost, as:‘home’ /} #{if olderPosts.size()}#{/if}
#{else}
There is currently nothing to read here.
#{/else}
Refresque la página y verifique que todo funciona según lo esperado.
Como puede ver, el template index.html
extiende el template main.html
. Dado que queremos brindar un layout común a todas las páginas de nuestra aplicación, con el título del mensaje y los links de autenticación, necesitamos modificar este archivo.
Edite el archivo /yabe/app/views/main.html
:
<!DOCTYPE html >
<html>
<head>
<title>#{get 'title' /}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" media="screen"
href="@{'/public/stylesheets/main.css'}" />
<link rel="shortcut icon" type="image/png"
href="@{'/public/images/favicon.png'}" />
</head>
<body>
Refresque y verifique el resultado. Parece que todo funciona, excepto que las variables blogTitle
y blogBaseLine
no aparecen en pantalla. Esto es debido a que no las hemos pasado a la llamada al método render(...)
. Por supuesto que puede agregarlas a la llamada a render()
en la acción index
. Pero dado que el archivo main.html
será utilizado como template base para todas las acciones de nuestra aplicación, no queremos tener que agregarlo manualmente cada vez.
Una manera de ejecutar el mismo código para cada acción de un controlador (o una jerarquía de controladores) es definiendo un interceptor @Before
.
Agreguemos el método addDefaults()
al controlador Application:
@Before
static void addDefaults() {
renderArgs.put("blogTitle", Play.configuration.getProperty("blog.title"));
renderArgs.put("blogBaseline", Play.configuration.getProperty("blog.baseline"));
}
Necesitará importar play.Play
en el archivo Application.java
.
Todas las variables agregadas a la colección renderArgs
estarán disponibles desde los templates. Note que el método lee los valores de las variables del objeto Play.configuration
. Este objeto permite acceder a la configuración del archivo /yabe/conf/application.conf
.
Agregue estas dos claves al archivo de configuración:
# Blog engine configuration
# ~~~~~
blog.title=Yet another blog
blog.baseline=We won't write about anything
Refresque la página principal y verifique que todo haya salido bien.
La página principal de nuestro sistema de blogs está casi lista, pero no se ve muy bien que digamos. Le agregaremos algunas plantillas de estilo para hacerla más atractiva. Como habrá notado, nuestro template principal main.html
incluye la hoja de estilos /public/stylesheets/main.css
. Nos quedaremos con ella pero le agregaremos nuevas reglas de estilo.
Puede descargar la hoja de estilos, y copiarla al archivo /public/stylesheets/main.css
.
Refresque la página y debería ver ahora una página con los estilos aplicados.
La página principal está terminada. Como de costumbre, grabamos los cambios efectuados en bazaar:
$ bzr st
$ bzr add
$ bzr commit -m "Home page"
Vaya a La página de comentarios.