Haz un juego de votación de imágenes con Node.js (Parte 1)

Node.js se está volviendo cada vez más popular. Este servidor de JavaScript es la herramienta perfecta para aplicaciones en tiempo real como chats, juegos multijugador y herramientas de colaboración. Pero también puede usarlo para crear aplicaciones web regulares. Todo lo que necesita hacer es elegir los marcos correctos. Esto es lo que haremos hoy. Codificaremos un juego de votación de imágenes tipo "Hot or Not" que almacenará sus datos en una base de datos tipo NoSQL.

El tutorial se dividirá en dos partes. El primero, que puede leer a continuación, cubre la configuración, la estructura del directorio y la base de datos. En la siguiente parte, cubriremos el enrutamiento y las vistas. Lea la parte 2.

La idea

Nuestra aplicación node.js se construirá sobre el marco Express, utilizará el motor handlebars para plantillas y nedb para almacenar datos. La aplicación permitirá a los visitantes votar fotos, una imagen a la vez. También habrá una lista de clasificación con las fotos ordenadas por votos. Solo se permitirá un voto por imagen por dirección IP.

No habrá JavaScript del lado del cliente en esta aplicación; todo se ejecutará en el servidor. Por ejemplo, al presionar el botón "Lindo" se envía un formulario, como en los viejos tiempos. Decidí seguir este camino para que pudieras centrar tu atención por completo en el código del lado del servidor y no quería complicar las cosas con bibliotecas del lado del cliente como Angular o Ember.

Instalando Node.js

Para seguir este tutorial, debe tener instalado node.js en su computadora. Esto es sencillo:simplemente obtenga el paquete correcto para su sistema operativo desde la página de descarga del nodo. Si está ejecutando Linux u OSX, deberá extraer el archivo en algún lugar, por ejemplo, en $HOME/node (donde $HOME es su directorio de inicio) y agregue $HOME/node/bin a su ruta editando su archivo .bashrc. Si está ejecutando Windows, utilice el instalador proporcionado en la página de descarga.

Si todo funciona correctamente, ejecutando el node comando en una ventana de consola le dará el símbolo del sistema de node.js.

Ejecución de la demostración

Si desea ejecutar la aplicación en este punto, debe descargar el código fuente como un archivo zip desde el botón que se encuentra cerca de la parte superior del artículo y extraerlo en algún lugar de su computadora. Luego debe navegar a la carpeta donde se encuentra el archivo index.js y ejecutar el npm install dominio. Esto descargará todas las bibliotecas requeridas del registro npm. Entonces todo lo que necesitas hacer es ejecutar node index.js ¡y tendrás tu propio juego de votación con imágenes en tu computadora!

Debido a que la aplicación solo permite un voto por foto desde la IP, después de haber votado por todas las fotos, puede eliminar el archivo /data/users para poder votar nuevamente.

La estructura del directorio

Primero, expliquemos cómo se organizará nuestro proyecto. Constará de una serie de carpetas y archivos, que deberá crear manualmente.

  • Los datos/ La carpeta contiene los archivos de la base de datos nedb. Son archivos de texto sin formato que contienen documentos JSON; incluso puede abrirlos en un editor de texto y editarlos.
  • Los módulos_nodos/ npm crea automáticamente la carpeta cuando ejecuta el comando de instalación de npm. Aquí es donde se guardan las bibliotecas descargadas.
  • El público/ La carpeta contiene JavaScript, CSS, imágenes y otros activos a los que debe acceder un navegador. Pon solo cosas que quieras que la gente vea allí.
  • Las vistas/ La carpeta contiene las plantillas que utiliza la aplicación. Se ejecutan a través del handlebars motor de plantillas de antemano, como verá cuando hablemos del archivo de rutas la próxima vez.
  • El paquete.json El archivo describe las dependencias de su aplicación (qué bibliotecas del registro npm deben descargarse), el nombre, la licencia del código y otra información. Crearemos este archivo en la siguiente sección.
  • El .js Los archivos contienen la lógica de la aplicación. Están organizados como módulos de node.js y están incluidos en index.js, que también es el punto de entrada de la aplicación. Ejecutas la aplicación ejecutando el comando node index.js .

Crea cada una de las carpetas y archivos. Puede dejar los archivos en blanco por ahora.

Creando el paquete.json

Una vez que tenga los archivos en su lugar, el siguiente paso para crear nuestra aplicación node.js es crear el archivo package.json. Describe cómo debería funcionar su aplicación, qué licencia tiene, su repositorio, autor y más (vea un ejemplo interactivo aquí). Node viene con una práctica utilidad que puede usar para crear rápidamente un archivo package.json válido. Abra su consola, navegue hasta el directorio del proyecto que contiene index.js y los otros archivos, y ejecute el siguiente comando:

npm init

La utilidad le hará algunas preguntas y luego creará su archivo package.json. A partir de ese momento, cuando instale nuevas bibliotecas con npm, deberá usar el indicador --save para que npm actualice su paquete.json por usted. Pruébelo ejecutando estos comandos:

npm install express --save
npm install nedb --save
npm install express3-handlebars --save

(Por supuesto, puede instalar los tres con un solo comando). Estos comandos indicarán al administrador de paquetes del nodo que descargue las bibliotecas express, nedb y express3-handlebars del registro, para guardarlas en los node_modules directorio y para actualizar la propiedad de dependencias de su package.json archivo.

Aquí está el contenido de nuestro paquete.json:

{
  "name": "picture-voting-game",
  "version": "0.0.1",
  "description": "This is a simple picture voting game with node.js",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "game",
    "picture",
    "voting"
  ],
  "author": "Martin Angelov",
  "license": "MIT",
  "dependencies": {
    "express": "~3.4.7",
    "nedb": "~0.9.4",
    "express3-handlebars": "~0.5.0"
  }
}

El módulo de base de datos

Ahora dirijamos nuestra atención a la base de datos. Como mencioné al comienzo del artículo, usaremos nedb para almacenar datos. Esta es una base de datos JavaScript pura y liviana. No es relacional (NoSQL) y le permite almacenar objetos (o documentos) JSON arbitrarios. Vive en el mismo proceso que su aplicación node.js, admite índices y es bastante rápido. No es adecuado para una gran cantidad de registros (para eso necesitará algo como MongoDB), pero es perfecto para aplicaciones más pequeñas como la que estamos escribiendo hoy. Todo lo que se requiere para usar esta base de datos es instalar el nedb paquete, que ya hicimos en la sección anterior.

Nuestra aplicación necesita dos tipos de conjuntos de datos:uno para las fotos y otro para los usuarios. Habrá un registro por usuario, y cada uno tendrá una dirección IP y una matriz con todas las imágenes por las que votó el usuario. En una base de datos normal como MySQL habríamos creado una tabla de base de datos separada con los votos, lo que habría complicado las cosas, pero no hay necesidad de hacerlo así aquí.

Para facilitar el mantenimiento del código, extraeremos la funcionalidad para crear los conjuntos de datos en su propio módulo node.js. Vea el código a continuación:

base de datos.js

// Require the nedb module
var Datastore = require('nedb'),
    fs = require('fs');

// Initialize two nedb databases. Notice the autoload parameter.
var photos = new Datastore({ filename: __dirname + '/data/photos', autoload: true }),
    users = new Datastore({ filename: __dirname + '/data/users', autoload: true });

// Create a "unique" index for the photo name and user ip
photos.ensureIndex({fieldName: 'name', unique: true});
users.ensureIndex({fieldName: 'ip', unique: true});

// Load all images from the public/photos folder in the database
var photos_on_disk = fs.readdirSync(__dirname + '/public/photos');

// Insert the photos in the database. This is executed on every 
// start up of your application, but because there is a unique
// constraint on the name field, subsequent writes will fail 
// and you will still have only one record per image:

photos_on_disk.forEach(function(photo){
    photos.insert({
        name: photo,
        likes: 0,
        dislikes: 0
    });
});

// Make the photos and users data sets available to the code
// that uses require() on this module:

module.exports = {
    photos: photos,
    users: users
};

Una cosa más que hace este módulo es escanear las /public/photos carpeta (donde se almacenan las imágenes de nuestros gatos) para los archivos que utilizan el módulo fs incorporado. Luego, las fotos se insertan en el conjunto de datos de fotos.

El valor asignado a la propiedad module.exports es el resultado que se devolverá cuando se requiera la base de datos.js()-d en otros archivos.

Continuar con la Parte 2

¡Esto concluye la primera parte del tutorial! En la segunda parte verás el resto de los módulos y las vistas. Léalo aquí.