Passa al contingut principal

Koalite: Tutorial Compojure II: Generando vistas con Hiccup

En el post anterior de este tutorial creamos la estructura del proyecto web para compojure y vimos los conceptos básicos necesarios para empezar a trabajar. Ha llegado el momento de entrar en materia y comenzar a construir la aplicación.


La aplicación


En este tutorial vamos a desarrollar una aplicación web sencilla, pero que nos va a permitir tocar varios puntos habituales en este tipo de aplicaciones: servir contenido estático, generar html dinámicamente y exponer un API accesible desde Javascript.


Como se me da bastante mal lo de buscar aplicaciones de ejemplo, vamos a reimplementar la misma aplicación que usamos en el tutorial de node.js + express + jquery: MegaFacts.


La idea es muy simple, crearemos una aplicación que nos permita manejar listas de facts, al estilo de los Chuck Norris Facts, Bruce Schneier Facts o Pérez-Reverte Facts. El aspecto de nuestra página principal (y única, ya que se tratará de una SPA), será algo similar a esto:


Mockup de la página de Mega Facts

En la parte izquierda mostraremos una lista de personas de las que conocemos facts. Al pulsar sobre una de ellas mostraremos en la parte central la lista de facts conocidos, permitiendo añadir nuevos facts.


Sirviendo contenido estático


En casi todas las aplicaciones es necesario servir contenido estático de una forma u otra. Podemos servir contenido estático desde una aplicación compojure creando una ruta usando la macro files. Para ello modificaremos nuestra definición de rutas (recordad que está en el fichero ./src/compojure_sample/handler.clj):



(defroutes app-routes
(GET "/" [] "Hello World")
(route/files "/public" {:root "public"})
(route/not-found "Not Found"))

Los parámetros de la macro files son la ruta física en disco donde se almacena el contenido estático y un map en el que podemos configurar varios aspectos, entre ellos la ruta lógica que se usará para acceder a los recursos.


Es importante tener en cuenta que la ruta física indicada a la macro files es relativa a la raíz del proyecto, es decir, a la ubicación en que se encuentra el fichero project.clj.


Usando Hiccup para crear páginas dinámicamente


En clojure existen unos cuantos sistemas de plantillas para generar páginas HTML y todos ellos son bastante fáciles de user con compojure, pero seguramente el más popular sea hiccup.


Para poder usar hiccup deberemos incluirlo como dependencia de nuestro proyecto en el fichero project.clj:



(defproject compojure-sample "0.1.0-SNAPSHOT"
:description "Sample compojure project"
:url "http://blog.koalite.com/2013/03/tutorial-compojure-i-creando-una-aplicacion-web-funcional/"
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.1.5"]
; Añadimos la dependencia de hiccup versión 1.0.2
[hiccup "1.0.2"]]
:plugins [[lein-ring "0.8.2"]]
:ring {:handler compojure-sample.handler/app}
:profiles
{:dev {:dependencies [[ring-mock "0.1.3"]]}})

Un aspecto interesante de hiccup para los que venimos de otro tipo de lenguajes es que en lugar de utilizar una sintaxis específica para la generación de HTML (Razor, Jade, Haml, etc.), se utiliza directamente código clojure (lo más parecido que he visto en un lenguaje estático es en Kotlin).


Todo ello además sin necesidad de definir estructuras de datos complejas, sino aprovechando las estructuras básicas del lenguaje, como comentaba hace no mucho al hablar de estructuras de datos sin esquema.


En hiccup cada elemento HTML se representa como un vector con el siguiente aspecto:



[:elemento#id.class {:attr1 val1 :attr2 val2} contenido]

El primer elemento es el elemento HTML propiamente dicho, además podemos usar selectores css para añadirle un id y una o más clases. A continuación podemos utilizar un map para definir atributos del elementos y por último indicaremos el contenido del elemento, que puede ser texto o más elementos anidados.


Para crear nuestra página principal (y única), añadiremos el fichero ./src/compojure_sample/views.clj con el siguiente contenido:



(ns compojure-sample.views
(:use hiccup.page)
(:use hiccup.element))

(defn index [hero-names]
(html5

[:head
(include-css "/public/css/style.css")
(include-js "/public/js/jquery-1.9.1.min.css")
[:title "Mega Facts"]]

[:body
[:div#container

[:div#header
[:h1 "Mega Facts"]]

[:div#content
[:div#left-column.column
[:h2 "Elige tu héroe"]
[:ul#heroes
(for [name hero-names]
[:li.hero-name (link-to "#" name)])]]
[:div#right-column.column
[:h2 "Facts"]
[:ul#facts]
[:label {:for "new-fact"} "Añadir nuevo fact:"]
[:textarea#new-fact]
[:a#add-new-fact {:href "#"} "Añadir"]]]

[:div#footer
[:a {:href "http://blog.koalite.com"}]]]]))

En este fichero la función index dentro del espacio de nombres y compojure-sample.views e incluimos en ella la generación del HTML. Además de las etiquetas se están usando algunas funciones de ayuda como link-to o include-js que nos permiten generar elementos HTML con una sintaxis más tersa. Sería algo parecido a los HtmlHelpers de ASP.NET MVC.


Aquí se aprecia una de las ventajas de usar el mismo lenguaje para las plantillas que en el resto de la aplicación: podemos usar cualquier construcción del lenguaje dentro de las plantillas.


Un ejemplo de esto lo tenemos en la forma en que se pasan parámetros a la vista. Al tratarse una función más de clojure, los parámetros se pasan como argumentos de la función y luego se pueden procesar como en cualquier función. En este caso se usa un for para genear una lista de elementos con los nombres de nuestros héroes:



[:ul#heroes
(for [name hero-names]
[:li.hero-name (link-to "#" name)])]]

Para utilizar esta vista, debemos modificar una vez las rutas de la aplicación, quedando algo así:



(ns compojure-sample.handler
(:use compojure.core)
(:require [compojure.handler :as handler]
[compojure.route :as route]
; Referenciamos el espacio de nombres de las vistas
[compojure-sample.views :as view]))

(defroutes app-routes
; Enlazamos la función que acabamos de crear a la raíz del sitio web
(GET "/" [] (view/index ["Chuck Norris", "Bruce Schneider", "Arturo Pérez Reverte"]))
(route/files "/public" {:root "public"})
(route/not-found "Not Found"))

Recordad que podemos comprobar que todo funciona ejecutando lein ring server. Además en caso de hacer cambios no es necesario reiniciar el servidor, sino que compojure los detectará y recompilará lo que sea necesario.


Próximos pasos


Ya tenemos una aplicación capaz de servir contenido estático y generar contenido dinámico. En el siguiente post veremos como crear el modelo interno de nuestra aplicación que nos permita gestionar la lista de héroes y facts, lo que nos permitirá profundizar un poco en técnicas para gestionar la mutabilidad en clojure.


El código fuente completo de este tutorial lo puedes encontrar en mi cuenta en github: https://github.com/jmhdez/compojure-sample . Siéntete libre de clonarlo, cambiarlo y jugar con él todo lo que quieras, y si te animas a realizar alguna corrección, estaré encantado de recibirla.


Posts relacionados:



  1. Tutorial node.js + express + jquery (II): Generando vistas con Jade

  2. Tutorial Compojure I: Creando una aplicación web funcional






via Planeta Código http://blog.koalite.com/2013/03/tutorial-compojure-ii-generando-vistas-con-hiccup/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+KoalitesBlog+%28Koalite%29

Comentaris

Entrades populars d'aquest blog

10 alternativas a Cuevana para ver películas online

10 alternativas a Cuevana para ver películas online : Durante este último tiempo, en Cuevana se sucedieron varios “problemas” por los cuales hubo que ajustar algunas cosas antes de tiempo (como el rediseño del sitio), que dejaron a algunos usuarios ciertos problemas para acceder a las películas o series del portal. Pero realmente esto es algo que no incumbe a los usuarios y, como sabemos, existen muchas otras alternativas a Cuevana dando vueltas por Internet, que intentaremos presentar aquí mismo. Los sitios que repasaremos funcionan del mismo modo que Cuevana, mediante la instalación de un plugin que permite visualizar los videos de Megaupload o WUShare, entre otros servicios, en una calidad de imágen realmente excelente. Tal como sucede con el más popular servicio, todos ellos tienen publicidad que en algunos casos resulta insoportable, pero como dice Federico en DotPod “a caballo regalado no se le miran los dientes”. Alternativas a Cuevana 1. Moviezet Posiblemente el mejor clon d

Sitio alternativo a Cuevana: Moviezet

Sitio alternativo a Cuevana: Moviezet : Nadie se quiere enfrentar al monstruo Cuevana , tan popular por estos días que es casi imposible ver tu serie favorita o tu película sin tener problema de saturación de tráfico. Pero hay proyectos muy sanos y prometedores, sobre todo porque están basados como una muy buena alternativa . Señores estamos hablando obviamente de un sitio alternativo a Cuevana, llamado Moviezet. Como bien dijimos, Moviezet es una excelente alternativa a Cuevana, ya que podremos ver películas y series de forma gratuita sin necesidad de que existan cortes – al mejor estilo Megavideo – y que podremos tener un seguimiento, es decir, si miramos una serie, podremos ver toda la lista con los capítulos disponibles. Lo que tiene de novedoso este sitio web Moviezet , es que tiene películas y series que quizá en Cuevana no se puedan conseguir, pero atención, que puede suceder lo mismo, pero al revés. Entonces aquí intervenimos nosotros y te daremos un sabio consejo, para no

Learn Composition from the Photography of Henri Cartier-Bresson

“Do you see it?” This question is a photographic mantra. Myron Barnstone , my mentor, repeats this question every day with the hopes that we do “see it.” This obvious question reminds me that even though I have seen Cartier-Bresson’s prints and read his books, there are major parts of his work which remain hidden from public view. Beneath the surface of perfectly timed snap shots is a design sensibility that is rarely challenged by contemporary photographers. Henri Cartier-Bresson. © Martine Franck Words To Know 1:1.5 Ratio: The 35mm negative measures 36mm x 24mm. Mathematically it can be reduced to a 3:2 ratio. Reduced even further it will be referred to as the 1:1.5 Ratio or the 1.5 Rectangle. Eyes: The frame of an image is created by two vertical lines and two horizontal lines. The intersection of these lines is called an eye. The four corners of a negative can be called the “eyes.” This is extremely important because the diagonals connecting these lines will form the breakdown