Algunas notas sobre Backbone JS

¿Qué es?

BackBone JS es una librería de unos 4kb que provee una estructura para aplicaciones que se basan fuertemente en javascript.

Provee “modelos” con bindeos de tipo key-value, eventos, colecciones con una API de funciones, vistas asociadas a los eventos, y conexión vía una interface RESTful con JSON.

Cómo funciona: cuando alguna propiedad del modelo cambia, se notifica a las vistas que “escuchan” los cambios en el modelo y las vistas se actualizan automáticamente a sí mismas según corresponda, sin la necesidad de manejarlas manualmente.

Permite separar más prolijamente los datos de la presentación. El modelo se sincroniza con el servidor mientras que las vistas escuchan cambios a los objetos suscriptos del modelo, y renderizan el HTML que les corresponde.

¿Reemplaza a jQuery?

No, no se superponen, más bien son complementarios, tienen alcances y usos diferentes. Backbone maneja abstracciones de un nivel más alto, mientras jQuery trabaja con el DOM, normaliza eventos, etc.

¿Por qué usar Backbone?

Porque muy frecuentemente el código de front-end se convierte en una madeja desprolija de callbacks anidados, manipulaciones al DOM, HTML de presentación, etc. Backbone ofrece una manera más limpia y elegante de manejar ese caos.

¿Dónde usar Backbone?

Backbone es ideal para front-ends pesados y con mucho manejo de datos.
Por ejemplo, una aplicación con 50 eventos diferentes, con un modelo de varios tipos de datos, con objetos con 6 métodos de persistencia y de lógica de negocio cada uno, con interacción entre objetos y elementos del DOM, etc. Como podrían ser la interfaz de GMail, Twitter, Facebook, y otras aplicaciones con un front-end cargado y complejo.
Backbone hace más fácil “navegar” y entender el código.

En definitiva

… en lugar de manejar un JSON enorme, toquetear el DOM manualmente y realizar muchas llamadas ajax, se trata de poder llegar a escribir:

book.save({title: “Lorem Ipsum”});


… y que todo el UI que referencia al libro se actualice automáticamente y los cambios se guarden en el servidor.

Modelo

Un modelo representa una entidad, y contiene los datos y buena parte de la lógica: conversiones, validaciones, propiedades computadas, etc.

var Game = Backbone.Model.extend({ 
        initialize: function(){ 
            alert(“¡Hola!”); 
        }, 
          defaults: { 
            name: ‘Default title’, 
            releaseDate: 2012, 
        } 
    }); 

/* New */
var juego = new Game({ name: “Maniac Mansion”,
releaseDate: 2012}); 

/* Get */
var release = juego.get(‘releaseDate’); 
 
/* Set (guarda en memoria, en cookies) */
juego.set({ name: “Maniac Mansion 2″});

/* Guardar (llama al servidor con POST por ser un nuevo objeto, sino sería una llamada PUT) */
juego.save();

Colección

Las colecciones en Backbone son esencialmente una colección de modelos.

Una colección de juegos:

var GamesCollection = Backbone.Collection.extend({ 
  model : Game, 
  } 
});

var GamesCollection = Backbone.Collection.extend({ 
  model : Game, 
  old : function() { 
    return this.filter(function(game) { 
      return game.get(‘releaseDate’) < 2000; 
    }); 
  } 
  } 
});

var games = new GamesCollection 
games.get(3); /* Retorna el juego con id=3 */

var GamesCollection = Backbone.Collection.extend({ 
  model : Game, 
  url: ‘/games’ 
  } 
}); 
 
var games = new GamesCollection 
games.fetch(); 

El método fetch hace una llamada asincrónica al servidor y popula la colección con los resultados.

Vista

Para los puristas de MVC, parece más un controlador que una vista. Tiene fundamentalmente dos tareas:

- Escuchar a los eventos disparados por el DOM, modelos y colecciones.

- Representar el estado de la aplicación y el modelo de datos al usuario.

GameView = Backbone.View.extend({ 
  tagName : “div”, 
  className: “game”, 
  render : function() { 
    /* código para renderizar el html */ 
  } 
}); 

render : function() { 
    $(this.el).html(“<b>” + this.model.get(‘name’) + “</b>”); 

El objeto el es el elemento del DOM al que hace referencia la vista. En este caso, el elemento div renderizará el nombre del juego.
Para HTML más complejo, lo mejor es usar templates. Por default, Backbone provee la solución de templates de Underscore.JS.

Definimos y atamos un evento a la vista.

events: { 
        ‘click .name’: ‘handleClick’ 
    }, 
 
handleClick: function(){ 
          alert(‘Clickeaste, chabón’); 

GameView = Backbone.View.extend({ 
    initialize: function (args) { 
        _.bindAll(this, ‘changeName’); 
        this.model.bind(‘change:name’, this.OnGameNameChanged); 
    }, 
}); 

En este ejemplo, cuando el atributo name del modelo cambie, se llamará a la función OnGameNameChanged. Además de change, Se puede hacer un polling de cambios usando add y remove. En el bind, se puede reemplazar model por collection para que escuchar cambios en la colección.
BindAll es una función de Underscore.JS para mantener el objeto this en el callback.

Controlador

Define la lógica de ruteo, relacionando una URL con una función javascript. Permite crear aplicaciones bookmarkeables usando hash tags (#).

var MyGameController = Backbone.Controller.extend({
  routes : {
    “say/:something” : “say”
  },
 
  say : function(something) {
    alert(something);
    /* Ej.:
http://myapp.root/#say/hello_world */
  }
});

var gameController = new MyGameController;
 
Backbone.history.start();

Aplicaciones de ejemplo

En la web hay varios ejemplos de aplicaciones hechas con Backbone JS. Van algunos links:

Hello Backbone.js: http://arturadib.com/hello-backbonejs/

Wine Cellar Tutorial: http://coenraets.org/blog/2011/12/backbone-js-wine-cellar-tutorial-part-1-getting-started/

Todos: http://documentcloud.github.com/backbone/examples/todos/index.html

Algunos links útiles…

http://documentcloud.github.com/backbone/

http://stackoverflow.com/questions/5418369/what-is-backbone-js

http://jonathanotto.com/blog/backbone_js_for_the_everyman.html

http://net.tutsplus.com/tutorials/javascript-ajax/getting-started-with-backbone-js/

Creando una aplicación MVC en Ruby on Rails en 5 minutos

Ruby es un lenguaje de programación dinámico y de código abierto enfocado en la simplicidad y productividad. Su elegante sintaxis se siente natural al leerla y fácil al escribirla. Sus características principales son:

• Interpretado: se ejecuta inmediatamente sin necesidad de compilador, aunque la ejecución es más lenta.

• Orientado a objetos: absolutamente todo es un objeto.

• Portable: funciona en múltiples plataformas (UNIX, Windows, DOS, Mac, etc.) sin necesidad de cambios.

• No-tipado: las variables no tienen un tipo.

• Garbage collector: built-in, sin necesidad de preocuparse por liberar memoria.

• Sintaxis fácil y clara.

• Totalmente gratuito, incluso para aplicaciones comerciales.

Ruby on Rails, también conocido como RoR o Rails es un framework de aplicaciones web de código abierto escrito en Ruby siguiendo el paradigma de la arquitectura MVC. Trata de combinar la simplicidad con la posibilidad de desarrollar aplicaciones del mundo real escribiendo menos código que con otros frameworks y con un mínimo de configuración. El lenguaje de programación Ruby permite la metaprogramación, de la cual Rails hace uso, lo que resulta en una sintaxis que muchos de sus usuarios encuentran muy legible. Está absado en los siguientes principios:

• Don’t Repeat Yourself: no duplicar las “piezas de información”.

• Convention Over Configuration: ganar simplicidad especificando sólo aspectos no convencionales.

• REST: patrón de diseño web basado en identificación de recursos.

ActiveRecord

ActiveRecord es la capa de Rails de mapeo relacional de objetos. Provee una interfaz orientada a objetos que se relacionan con una base de datos, para hacer el desarrollo más simple y amigable para el desarrollador. Es un ORM (object-relational mapping): hace las traducciones entre objetos Ruby y la base de datos, manejando registros y relaciones. La librería ActiveRecord de Ruby crea un modelo de negocio persistente desde los objetos de negocio y las tablas de datos, unificándose la lógica y los datos en un solo paquete. ActiveRecord agrega herencia y asociaciones al patrón Active Record común, dándole más potencia.

Scaffolding

Rails provee Scaffolding, una técnica para construir vistas, modelos, controladores, bases de datos, etc. a partir de operaciones simples. Veamos cómo se utiliza:

1. Creación de la aplicación

Ejecutar en la consola el siguiente comando:

$ rails new videoclub
Esto armará toda una estructura de carpetas para la aplicación, tales como config, db, doc, controllers, views, script, tests, etc.

2. Creación de la base de datos

Ejecutar en la consola el siguiente comando:
$ rake db:create

Esto creará en la carpeta db dos bases de datos: la de desarrollo y la de tests. Por default, la base de datos es SQLite3, pero desde ya que puede ser otro motor.

3. Crear un controlador

Ejecutar en la consola el siguiente comando:
$ rails generate controller home index
Rails creará no sólo el archivo del controlador, sino además la vista correspondiente a la acción index: app/views/home/index.html.erb

4. Establecer la homepage

Ejecutar en la consola el siguiente comando:
$ rm public/index.html

5. Crear una clase del modelo

Ejecutar en la consola los siguientes comandos:
$ rails generate scaffold Cliente name:string lastname:string
$ rake db:migrate

Estas instrucciones no sólo crearán el archivo app/models/cliente.rb, sino que además modificarán la base de datos (ActiveRecord mediante) para incluir este modelo en la estructura de tablas.

6. Levantar el web server y ver la aplicación

Ejecutar en la consola el siguiente comando:
$ rails server

Con el web server corriendo, la aplicación podrá ser visualizada accediendo a http://localhost:3000.

¡Y listo! Ahora habrá que modificar la vista para que haga algo con el modelo, complejizar el controlador, etc., pero ya disponemos, tras unos breves pasos, de una aplicación con estructura MVC, una vista, un controlador y un modelo, así como la base de datos asociada al mismo.

Algunos links interesantes

http://guides.rubyonrails.org/getting_started.html (sobre el que basamos este ejemplo de aplicación)

http://railsinstaller.org/

http://www.ruby-doc.org/

Agregando un proyecto a integración continua con Jenkins

Vamos a mostrar, muy sucintamente, cómo agregar un proyecto de Visual Studio a un servidor de integración continua Jenkins. Para eso, veamos primero las herramientas que utilizaremos:

- Jenkins (http://jenkins-ci.org/): es una aplicación que monitorea la ejecución repetida de jobs automatizados que se utilizan para integración continua (compilación de proyectos, ejecución de tests unitarios, análisis de cobertura de código, etc.).

- MSBuild: es una plataforma que permite ejecutar builds automatizados de proyectos de Visual Studio, sin necesidad de tener el IDE instalado.

Ahora vayamos paso por paso.

1. Crear el archivo de MSBuild

Este es un posible archivo de msbuild utilizado para un proyecto:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>        

    <PropertyGroup>
        <WorkingDirectory>C:\.hudson\workspace\DM.API\CheckoutService\branches\APIv1.1\src</WorkingDirectory>
        <ConnectionStringNoDB>Server=DMCI01\SQL02;Trusted_Connection=True;</ConnectionStringNoDB>
        <ConnectionString>Server=DMCI01\SQL02;Trusted_Connection=True;database=DMSandboxAPI;</ConnectionString>
    </PropertyGroup>    

    <ItemGroup>
        <CreateDBScripts Include="$(WorkingDirectory)\DM.Services.Process.API\Sandbox Scripts\DB\*.sql" />
        <TableScripts Include="$(WorkingDirectory)\DM.Services.Process.API\Sandbox Scripts\Tables\*.sql" />
        <DataScripts Include="$(WorkingDirectory)\DM.Services.Process.API\Sandbox Scripts\Data\*.sql" />
    </ItemGroup>        

    <Target Name="CreateSandboxDB">
        <ExecuteDDL ConnectionString="$(ConnectionStringNoDB)" Files="@(CreateDBScripts)" ContinueOnError="false" />        <ExecuteDDL ConnectionString="$(ConnectionString)" Files="@(TableScripts)" ContinueOnError="false" />
        <ExecuteDDL ConnectionString="$(ConnectionString)" Files="@(DataScripts)" ContinueOnError="false" />
    </Target>        

</Project>

Los tags <PropertyGroup> especifican que existen propiedades que toman cierto valor. Por ejemplo, la propiedad <WorkingDirectory> determina el path donde se encuentra el código, así como la propiedad <ConnectionString> especifica el string de conexión a base de datos a utilizar.

El tag <ItemGroup> representa un archivo a utilizar. En el caso de TableScripts, por ejemplo, referencia a todos los archivos .sql de una carpeta.

El tag <Target> contiene un conjunto de tareas a ejecutar secuencialmente. En nuestro ejemplo, el target “CreateDatabase” define la ejecución de tareas ExecuteDDL, que ejecutan scripts de base de datos, en nuestro caso archivos .sql.

2. Agregar el proyecto a Jenkins

CreateProject

Basta con navegar a Jenkins y agregar una nueva tarea desde el menú especificándole un nombre.

3. Configurar el proyecto Jenkins

Existe un link de Configurar dentro de la pantalla del proyecto creado. La vista de configuración es esta:

Config_1

Config_2

3.1 Código fuente

Bajo la sección “Source Code Management”, establecemos que el código fuente se obtiene desde un repositorio de tipo subversion, vía una URL. La opción de “Local module directory” permite especificar bajo qué subcarpeta del proyecto se guardará el código fuente.

3.2 Build triggers

La opción “Poll SCM” bajo la sección “Build Triggers” tiene el valor “* * * * *”, que significa que se hará un poll cada un minuto para verificar si existen cambios en el código fuente que disparen el proceso de build.

3.3 Build

3.3.1 Ejecución del archivo msbuild

En el primer item “Build a Visual Studio project or solution using MSBuild”, informamos a Jenkins que cuando se dispare el proceso ejecute el archivo de msbuild en el que definimos las tareas a realizar (creación de base de datos).

3.3.2 Compilación

En el segundo item “Build a Visual Studio project or solution using MSBuild”, definimos que se compile la solución en modo Debug.

3.3.3 Ejecución de Tests

En el item “Execute Windows batch command”, establecemos que EL NUnit ejecute los tests unitarios implicados en la dll del proyecto de test unitarios, y arroje esos resultados en un archivo xml.

Find & Replace con Regular Expressions

Si quiero reemplazar

ConfigurationManager.AppSettings[lo_que_sea] 
por:
ConfigurationHelper.GetAppSettingValue(lo_que_sea)

Se pueden usar regular expressions:
En la ventana de find & replace de VS, eligiendo Use regular expressions, se pone:
Find what: ConfigurationManager.AppSettings\[{.@}\]
Replaced with: ConfigurationHelper.GetAppSettingValue(\1)
El \1 significa que use lo que está entre llaves en la expresión regular…