Quantcast
Channel: carlosazaustre.es - Formación y Desarrollo en JavaScript
Viewing all 164 articles
Browse latest View live

Cómo implementar una API REST con MongoDB + Node.js usando Express v4

$
0
0

nodejs-mongodb-api

Hace algún tiempo publiqué un tutorial de como desarollar una API Rest en Node.js con el framework Express. Ese tutorial funciona perfectamente si usas la versión 3.x del framework, pero si vas a cambiar a la versión 4, hay algunas cosas que han cambiado. Es por ello que voy a explicar a continuación como hacer una API REST para vuestras aplicaciones web desde cero, utilizando para ello la versión 4 del framework más usado de Node.js, Express.

Cambios en Express v.4 con respecto a la v.3

En la nueva versión, varios Middlewares han sido eliminados de Express y ahora son dependencias aparte, como es el caso de bodyParser, compress, logger, session, favicon, methodOverride, etc…

Ya no se encuentran dentro del paquete Express y hay que importarlos aparte si se van a usar. De esta manera Express queda más ligero. Por lo tanto uno de nuestros primeros cambios será ese:

{
 "name": "node-api-rest-example",
 "version": "2.0.0",
 "dependencies": {
 "mongoose": "~3.6.11",
 "express": "^4.7.1",
 "method-override": "^2.1.2",
 "body-parser": "^1.5.1"
 }
}

Nuestro fichero app.js será así:

var express = require("express"),
    app = express(),
    bodyParser  = require("body-parser"),
    methodOverride = require("method-override");
    mongoose = require('mongoose');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());

var router = express.Router();

router.get('/', function(req, res) {
   res.send("Hello World!");
});

app.use(router);

app.listen(3000, function() {
  console.log("Node server running on http://localhost:3000");
});

Si os fijáis, antes la declaración de los middlewares a usar, lo hacíamos dentro de app.configure(), ahora con Express v.4 ya no es necesario.

También se ha eliminado el app.router().Ahora las rutas se pueden declarar con app.route(nombre_de_la_ruta) seguido de los verbos .get(), .post(), etc… y podemos crear una instancia para ellas con express.Router(). En este primer ejemplo vamos hacer que sólo reciba una petición GET del navegador y muestre en el mismo la frase Hello World

Para ejecutar este pequeño código sólo tienes que escribir en consola lo siguiente y abrir un navegador con la url http://localhost:3000

$ npm install
$ node app.js
Node server running on http://localhost:3000  

Si todo va bien, esto es lo que veréis:

Hello World Node

Los modelos que vamos a utilizar son los mismos que en el anterior tutorial, y cambian poco en esta versión. Tan solo hay cambios en la forma de declarar las rutas.

Creación de modelos con Mongoose

(Archivo: models/tvshow.js) Este archivo representa el modelo de datos, el cual modelamos con la librería Mongoose. Incluye la información de una serie de TV, como pueden ser su título, el año de inicio, país de producción, una imagen promocional, número de temporadas, género y resumen del argumento:

var mongoose = require('mongoose'),
    Schema   = mongoose.Schema;

var tvshowSchema = new Schema({
  title:    { type: String },
  year:     { type: Number },
  country:  { type: String },
  poster:   { type: String },
  seasons:  { type: Number },
  genre:    { type: String, enum:
  ['Drama', 'Fantasy', 'Sci-Fi', 'Thriller', 'Comedy']
        },
  summary:  { type: String }    
});

module.exports = mongoose.model('TVShow', tvshowSchema);

Con esto ya podemos implementar la conexión a la base de datos y la importación de los modelos en el archivo app.js añadiendo las siguientes líneas:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/tvshows', function(err, res) {
    if(err) throw err;
    console.log('Connected to Database');
});

var models = require('./models/tvshow')(app, mongoose);

Para que esto funcione en nuestro entorno local, necesitamos tener instalado MongoDB. Dependiendo de vuestro sistema operativo de hace de una forma u otra. Aquí tenéis la documentación oficial. Si tenéis Mac, se instala de la misma manera que Node.js:

$ brew update
$ brew install mongodb

Una vez hecho esto, para poder iniciar MongoDB debes ejecutar en otra terminal:

$ mongod
all output going to: /usr/local/var/log/mongodb/mongo.log  

Con Mongo arrancado ya podemos ejecutar la aplicación como antes con node app.js desde la terminal, si todo va bien tendremos algo en la pantalla como esto:

$ node app.js
Node server running on http://localhost:3000  
Connected to Database  

Ahora desde otra terminal, podemos entrar al shell de MongoDB y comprobar que la base de datos se ha creado correctamente. Para ello ejecutamos el comando mongo

$ mongo
MongoDB shell version: 2.4.1  
connecting to: test  
> use tvshows
switched to db tvshows  
> show dbs
local    0.078125GB  
tvshows    (empty)  
>_

Controladores

Las los controladores de las rutas de nuestro API los vamos a crear en un archivo aparte que llamaremos controllers/tvshows.js. Gracias a exports conseguimos modularizarlo y que pueda ser llamado desde el archivo principal de la aplicación. El código de a continuación es el comienzo del archivo con la primera función que será la que devuelva todos los registros almacenados:

//File: controllers/tvshows.js
var mongoose = require('mongoose');
var TVShow  = mongoose.model('TVShow');

//GET - Return all tvshows in the DB
exports.findAllTVShows = function(req, res) {
    TVShow.find(function(err, tvshows) {
    if(err) res.send(500, err.message);

    console.log('GET /tvshows')
        res.status(200).jsonp(tvshows);
    });
};

De esta manera tan sencilla, al llamar a esta función findAllTVShows se envia como respuesta toda la colección de “tvshows” almacenada y en formato JSON. Si queremos que solo nos devuelva un registro con un identificador único, tenemos que crear una función tal que la siguiente:

/GET - Return a TVShow with specified ID
exports.findById = function(req, res) {
    TVShow.findById(req.params.id, function(err, tvshow) {
    if(err) return res.send(500. err.message);

    console.log('GET /tvshow/' + req.params.id);
        res.status(200).jsonp(tvshow);
    });
};

Con las funciones find() y findById() podemos buscar en la base de datos a partir de un modelo. Ahora vamos a desarrollar el resto de funciones que nos permitirán insertar, actualizar y borrar registros de la base de datos. La función de a continuación sería la correspondiente al método POST y nos permitirá añadir un nuevo objeto a la base de datos:

//POST - Insert a new TVShow in the DB
exports.addTVShow = function(req, res) {
    console.log('POST');
    console.log(req.body);

    var tvshow = new TVShow({
        title:    req.body.title,
        year:     req.body.year,
        country:  req.body.country,
        poster:   req.body.poster,
        seasons:  req.body.seasons,
        genre:    req.body.genre,
        summary:  req.body.summary
    });

    tvshow.save(function(err, tvshow) {
        if(err) return res.send(500, err.message);
    res.status(200).jsonp(tvshow);
    });
};

Primero creamos un nuevo objeto tvshow siguiendo el patrón del modelo, recogiendo los valores del cuerpo de la petición, lo salvamos en la base de datos con el comando .save() y por último lo enviamos en la respuesta de la función.

La siguiente función nos permitirá actualizar un registro a partir de un ID. Primero buscamos en la base de datos el registro dado el ID, y actualizamos sus campos con los valores que trae el cuerpo de la petición

//PUT - Update a register already exists
exports.updateTVShow = function(req, res) {
    TVShow.findById(req.params.id, function(err, tvshow) {
        tvshow.title   = req.body.petId;
        tvshow.year    = req.body.year;
        tvshow.country = req.body.country;
        tvshow.poster  = req.body.poster;
        tvshow.seasons = req.body.seasons;
        tvshow.genre   = req.body.genre;
        tvshow.summary = req.body.summary;

        tvshow.save(function(err) {
            if(err) return res.send(500, err.message);
      res.status(200).jsonp(tvshow);
        });
    });
};

Y por último para completar la funcionalidad CRUD de nuestra API, necesitamos la función que nos permita elminar registros de la base de datos y eso lo podemos hacer con el código de a continuación:

//DELETE - Delete a TVShow with specified ID
exports.deleteTVShow = function(req, res) {
    TVShow.findById(req.params.id, function(err, tvshow) {
        tvshow.remove(function(err) {
            if(err) return res.send(500, err.message);
      res.status(200);
        })
    });
};

Volvemos a nuestro archivo principal, app.js y declaramos las rutas, siguiendo las pautas de Express v.4

var TVShowCtrl = require('./controllers/tvshows');

// API routes
var tvshows = express.Router();

tvshows.route('/tvshows')
  .get(TVShowCtrl.findAllTVShows)
  .post(TVShowCtrl.addTVShow);

tvshows.route('/tvshows/:id')
  .get(TVShowCtrl.findById)
  .put(TVShowCtrl.updateTVShow)
  .delete(TVShowCtrl.deleteTVShow);

app.use('/api', tvshows);

Para probarlo seguimos los mismos pasos que hicimos en el tutorial de la versión 3 y tendremos nuestra API REST funcionando.

El código completo de este tutorial lo puedes en este repositorio de GitHub, en la rama feature-express4. Espero que os sirva!


Cómo configurar tu servidor cloud en DigitalOcean

$
0
0

digitalocean-Iaas DigitalOcean es un IaaS (Infraestructura como Servicio) como pueden ser los servidores EC2 de Amazon Web Services, aunque a mi parecer son más sencillos de usar y la interfaz es mucho más limpia y clara.

También es mejor el precio, puedes tener un droplet que es como llaman aquí a las maquinas virtuales, igual que la estancia micro que te da gratis un año Amazon (luego cuesta alrededor de 16$ al mes), por 5$ al mes, y por 10$ al mes un “pepino” ;) Además son discos SSD, es decir, miel de romero!

En este tutorial voy a explicar como registrarse en DigitalOcean y configurar nuestro primer servidor Linux en el que poder desplegar nuestras aplicaciones Web.

Nos dirigimos a la página web de DigitalOcean y nos registramos con un email y una contraseña. En el siguiente paso nos pedirán nuestros datos (nombre, apellidos, dirección y un número de tarjeta de crédito/débito) los añadimos y ya tenemos nuestra cuenta en DigitalOcean. Nos llegará un correo de confirmación a nuestro email, pinchamos en el link para confirmar y listo.

Screen Shot 2014-07-27 at 23.34.55

Ahora elegimos que máquina queremos, en mi caso elijo la más barata que para empezar nos sobra. 512 Mb de RAM, 1 CPU, 20GB de Disco SSD y 1TB de transferencia mensual (si lo superas, el GB adicional cuesta 0,02$)

Screen Shot 2014-07-27 at 23.03.35

La región, en mi caso elegí Londres por ser el más cercano a España, para la latencia.

Screen Shot 2014-07-27 at 23.04.52

Ya podemos acceder a nuestro panel de control y en el tendremos que configurar que software queremos instalar. En mi caso elegí una distribución Ubuntu 14.04 x64.

Screen Shot 2014-07-27 at 23.04.44

Podemos instalar aplicaciones adicionales, como Ruby, Django, PHP, etc… En mi caso elijo instalar Node para ahorrarme instalarlo via terminal, pero si queremos podemos hacerlo más adelante por SSH.

Screen Shot 2014-07-27 at 23.05.59

Ya tenemos todo, lo único que nos queda es poder acceder via SSH por terminal para poder configurar nuestro servidor, realizar despliegues, etc… Para ello primero necesitamos importar nuestra clave RSA pública o crear una nueva. En Mac OS se realiza así:

ssh-keygen -t rsa -C "your_email@example.com"  
# Creates a new ssh key, using the provided email as a label
# Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/you/.ssh/id_rsa): [Press enter]
Enter passphrase (empty for no passphrase): [Type a passphrase]  
# Enter same passphrase again: [Type passphrase again]
Your identification has been saved in /Users/you/.ssh/id_rsa.  
# Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
# The key fingerprint is:
# 01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db your_email@example.com

Ejecutamos cat ~./.ssh/id_rsa.pub para ver el contenido de nuestra clave pública, copiarla en el portapapeles e ir a la sección SSH Keys del panel de control y pegarla ahí. Con esto DigitalOcean nos permite acceder via SSH desde nuestra máquina local.

Screen Shot 2014-07-28 at 00.03.02

¿Cómo accedemos vía SSH? En nuestro panel de control vemos nuestra lista de Droplets y en ella podemos ver la IP de nuestro servidor, en este caso, por ejemplo, aquí sería la 178.140.2.2 Screen Shot 2014-07-28 at 00.08.04

Con esos datos podemos acceder asi en nuestra máquina local

$ ssh root@178.140.2.2
root@178.140.2.2's password:  
Welcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64)

 * Documentation:  https://help.ubuntu.com/

  System information as of Sun Jul 27 17:16:56 EDT 2014

  System load:  0.0               Processes:           67
  Usage of /:   7.2% of 19.56GB   Users logged in:     0
  Memory usage: 10%               IP address for eth0: 178.62.36.77
  Swap usage:   0%

  Graph this data and manage this system at:

https://landscape.canonical.com/

Last login: Sun Jul 27 17:16:57 2014 from xxx.xxx.xxx.xxx  
root@tudroplet:~#  

La password que nos pide, nos la han enviado al email con el que nos hemos registrado, y la primera vez que nos logueemos via SSH nos permite cambiarla por una propia.

Con esto ya tenemos nuestro propio servidor en la nube y ahora ya solo queda instalar el software que necesitemos (Django, Nginx, MongoDB, Redis, etc…) y empezar a desplegar en producción

Fuentehttps://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server

#Hack4Good, el mayor hackathon global por el cambio climático

$
0
0

Fotografía © hack4good.io

hack4good_banner

Éste próximo fin de semana (12, 13 y 14 de septiembre) se celebra el #Hack4Good, un hackathon global por el cambio climático. En él participan 50 ciudades de todo el mundo y en Madrid lo organiza HackathonLovers, comunidad de la que soy miembro, con la ayuda de los colaboradores Kunlabori (por el espacio), CartoDB (por el avituallamiento) y GeekList (Organizador global).

Para participar no tienes que hacer nada más que apuntarte en nuestro Meetuphttp://www.meetup.com/Hackathon-Lovers/events/201739262/ ¿A que esperas? :)

¿Quieres poner a prueba tus habilidades como desarrollador y, al mismo tiempo, contribuir a una buena causa?, ¿Te ves capaz de construir una aplicación que solucione algunos de los retos que presenta el cambio climático?, ¿Y si te juntamos en una sala con un montón de hackers como tú, durante 48 horas?

¿Te ha picado la curiosidad? ¡Úšnete a #hack4good! Durante 48 horas, desarrolladores de 50 ciudades de todo el mundo trabajarán para dar solución a algunos de los retos más desafiantes que plantea el cambio climático.

Si eres de Madrid, no tienes excusa para no venir. ¡Te esperamos! Y en cualquier caso, siempre puedes apuntarte como participante online. ¡Nadie se queda fuera de #hack4good!

¿Y cuánto vale? 0 €. Nada. Gratis. Y te damos de comer y beber.

Para apuntarte, debes inscribirte, además de en este meetup, en la página oficial del evento:https://geekli.st/hackathon/hack4good-06/madrid

Co-organizadores:

Cómo instalar Node.js en Ubuntu

$
0
0

ubuntunode

Aunque Node.js está incluido en algunos repositorios de paquetes de Ubuntu, en ocasiones el uso del comando apt-get install no funciona correctamente, no instala una versión reciente, no se añade al PATH, etc…. A continuación veremos una forma de instalarlo sin problemas y la versión que nosotros queramos.

La alternativa es usando NVM (Node Version Manager)

Lo primero es actualizar los repositorios de Ubuntu y obtener los que nos permiten crear paquetes

$ sudo apt-get update
$ sudo apt-get install build-essential libssl-dev

Una vez hecho esto, descargamos el script de instalación de nvm desde Github

$ curl https://raw.githubusercontent.com/creationix/nvm/<span class="highlight">v0.7.0</span>/install.sh | sh

Esto descargará el script y lo ejecutará. Lo instalará dentro del directorio .nvm y añadirá unas lineas al fichero .profile, ambos situados en el directorio home de tu usuario de Ubuntu.

Para obtener acceso a la funcionalidad nvm, necesitamos salir de Ubuntu y volver a entrar, o una forma mucho más cómoda es ejecutar el siguiente comando que recargará el archivo en la terminal

$ source ~/.profile

Hecho esto ya podemos instalar la versión de Node.js que queramos. Podemos ver que versiones existen con

nvm ls-remote  

En mi caso he instalado la última versión estable

$ nvm install 0.10.31

Si escribimos lo siguiente podemos ver que versiones de Node y NPM tenemos instaladas en nuestro servidor Ubuntu

$ node -v
v0.10.31  
$ npm -v
1.4.23  

Resumen del Codemotion 2014

$
0
0

Fotografía © Codemotion
Codemotion

IMG_1361

Este fin de semana se ha celebrado la edición 2014 del Codemotion en Madrid. Es un evento de 2 días que junta a todas las comunidades de desarrolladores de España para presentar lo mejor de cada tecnología.

Allí estuvimos Paola y yo, como miembros del equipo Chefly, gracias a Hackathon Lovers que dió una magnífica charla sobre Hackathones.

Durante estos dos días se dieron un total de 112 charlas y 16 talleres repartidos en 8 tracks. Es imposible asistir a todas, así que me administré como pude para ir a las que me resultaran más interesantes y útiles para lo que me dedico. En este post he querido resumir todo el material que he podido recopilar de estos dos geniales días. Seguramente me deje alguna charla o presentación por el camino. No son todas las que son, pero son todas las que están. Espero que os sirvan, hay material de estudio para rato :)

Node.js FTW

El primer día Alex Fernandez @pinchito, dió su ya conocida charla de Escalabilidad con Node.js, donde ya alcanza las 85.000 peticiones por segundo sin despeinarse. En este enlace tenéis las slides. Su charla creo que no fue grabada, pero en el canal de vimeo de la Sala CAMON de Madrid tenéis este video de la misma charla hace ya unos meses donde por aquel entonces manejaba 40.000 peticiones por segundo:

Trucos de escalabilidad: pasando las cuarenta mil peticiones por segundo from Camon Madrid on Vimeo.

A primera hora no pude llegar, y me perdí la charla Lean Node.js de Ricardo Borillo. Pero mi compi Adolfo estuvo allí y me pasó los apuntes. Os dejo el enlace a sus slides aquí.

Autenticación en Angular JS

Después del coffee break asistí a la charla de Álvaro Sánchez-Mariscal y Daniel Ortega sobre autenticación basada en tokens en AngularJS. Me gustó mucho esta charla que me aclaró bastantes ideas en torno los metodos de autenticación sin estado para tener separado tu Backend en un API REST y tu frontend en una aplicación Single Page App. Estas son sus slides:

Docker

Después de comer me pasé por la charla de Daniel Lobato sobre Docker y la plataforma Foreman. Docker todavía es un mundo que no controlo mucho, en todo caso me pareció interesante la charla. Estas fueron sus slides:

Técnicas de Guerrilla Frontend

Y en la misma sala disfrutamos de la genial charla de Xavi Julian Olmos sobre Técnicas de Guerrilla Frontend. Muchísimo material y buenos consejos para estructurar nuestros proyectos Frontend. En este enlace de Google Drive tenéis las slides. Recomendadísimas!

Desarrollo Ágil y SCRUM

A las charlas de Juanma Gómez no pude asistir, pero os la recomiendo encarecidamente si queréis ser ágiles en vuestros desarrollos y proyectos.

SVG

La mañana del sábado la comencé con Sara Soueidan y su charla sobre Working with SVG, A primer. Un primer contacto con SVG y algunas herramientas para poder usar gráficos de vectores en nuestros proyectos webs con facilidad:

Hackathones

IMG_1377

No podía pasar por alto la genial charla sobre Hackathones que dieron Adolfo Sanz de Diego y Jorge Arévalo mis compis de Hackathon Lovers. Como pasar de 0 a producción en 24 horas y principales errores que se cometen en los hackathones.

JavaScript y más allá!

El resto del día, hasta el cierre fue JavaScript non-stop. Comenzando por Sergio Arbeo y su charla Lo que la cafeína le hizo a JavaScript comentándonos las principales novedades de ECMAScript 6 y como bebe de CoffeeScript. Os dejo con sus slides y una charla anterior en MadridJS que la complementa sobre Generadores.

Y para cerrar estuvimos en la charla de Lorenzo González Gascón sobre Directivas en AngularJS, contándonos trucos y técnicas para entender como usarlas correctamente y sacar provecho de ellas. Muy recomendable. Estas fueron sus slides:

Como podéis ver aquí hay material para consumir y asimilar de aquí a fin de año :D. Espero que os sea útil como me lo está siendo a mi y muchas gracias al Codemotion por la organización y el magnífico nivel de las charlas y sus ponentes. ¡El año que viene más!

IMG_1362

Cómo conectarte remótamente a tu base de datos MongoDB

$
0
0

MongoDB

En este artículo vamos a ver como dar seguridad a nuestra base de datos remota de producción y a su vez como conectarnos de manera remota desde nuestro entorno local.

Primero de todo inicia una instancia de MongoDB en tu servidor, sin el flag de autenticación:

mongod --port 27017 --dbpath /data/db1  

Creamos un usuario administrador que será el root que administre todas las bases de datos y será con el que nos conectemos por terminal (MongoShell) desde el servidor:

use admin
db.createUser(
  {
    user: "myServerAdmin",
    pwd: "password",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
);

Reinicia la instancia de MongoDB, esta vez con la autorización activada:

mongod --auth --config /etc/mongodb/mongodb.conf  

Ahora para conectarnos al MongoShell necesitamos hacerlo mediante el usuario administrador:

mongo --port 27017 -u myServerAdmin -p password --authenticationDatabase admin  

Una vez conectados, vamos a crear un usuario adicional que gestione la base de datos que utilizará tu aplicación. Que solo pueda acceder a esa base de datos y con permisos de Lectura/Escritura. Este será el que utilicemos para conectarnos desde nuestra aplicación backend.

Es importante que sea un usuario “no-root” el que se conecte desde nuestra app para evitar “disgustos” y es una capa importante de seguridad para nuestro backend.

use myDatabase
db.createUser(
    {
      user: "myUser",
      pwd: "12345678",
      roles: [
         "roles" : [ { "role" : "readWrite", "db" : "myDatabase" }
      ]
    }
);

Para poder conectarnos remotamente, edita el fichero /etc/mongod.conf

Cambia el campo bind_ip = 127.0.0.1, por la IP de tu servidor, y aprovecha a cambiar el campo port = 27017 por otro diferente, para mayor seguridad

Reinicia mongo para aplicar los cambios.

sudo service mongod restart  

Ahora si queremos conectarnos por el MongoShell a nuestra instancia de mongo, deberemos escribir el siguiente comando desde la terminal:

mongo --host x.x.x.x --port xxxxx -u myServerAdmin -p password --authenticationDatabase admin  

siendo x.x.x.x la IP de tu servidor y xxxxx el puerto que configuraste en el fichero mongod.conf

Y para conectarnos mediante una URI String desde nuestra aplicación backend, la URI será:

mongodb://myUser:12345678@x.x.x.x:xxxxx/myDatabase  

Configuración de Robomongo.

Robomongo es una aplicación para Mac, Windows y Linux para conectarse a bases de datos Mongo, de una manera visual, sustituyendo o complementando a la terminal y al MongoShell.

La configuración en Robomongo para conectarse remotamente a una base de datos por SSH es diferente a la conexión a tu base de datos local. Estas son las pestañas que debes configurar

En la pestaña Conexión, además de un nombre para identificar a la conexión, necesitas incluir la dirección IP de tu servidor (x.x.x.x) y el puerto que configuraste en el fichero mongod.conf (xxxxx)

robomongo_conexion

En la pestaña Autenticación, indica la base de datos “admin” para poder entrar con el nombre de usuario y la contraseña del usuario administrador que creamos (myServerAdmin)

robomongo_auth

Por último en la pestaña SSH, indica la dirección IP de tu servidor, el puerto de SSH (el 22 es el por defecto si no lo has cambiado), el nombre de usuario con el que puedes entrar en tu servidor por SSH y la contraseña

robomongo_ssh

Con esto podrás acceder con Robomongo a la base de datos remota de tu aplicación.

Fuentes:

Cómo migrar de Wordpress a Ghost

$
0
0

Recientemente he migrado mi blog de un hosting compartido a un servidor privado en DigitalOcean, y ya de paso he cambiado de sistema, de Wordpress a Ghost.

Ghost es un sistema de Blogging que corre bajo Node.js, todo muy hipster, ya sabéis :P

La migración es sencilla, pero laboriosa. Hay que seguir unos cuantos pasos para lograr mantener los artículos, las imágenes y los comentarios. Paso a relatarlos aquí según los tutoriales y artículos que he ido encontrand por internet. Vamos a ello!

Migrar imágenes de Wordpress a Ghost con Cloudinary

Lo primero que necesitas es salvar las imágenes que has utilizado en los post de tu blog Wordpress. Una opción es guardarlas en tu ordenador una a una y luego volverlas a subir en tu nuevo blog Ghost. Esto, a parte de una locura, te puede llevar años. Hay una opción mucho más ágil y menos dolorosa.

Regístrate en Cloudinary, que es un SaaS para subir y gestionar imágenes. Este servicio tiene una cuenta gratuita que te permite subir hasta 75.000 imágenes, lo cual para gestionar las imágenes que tendrás en Wordpress será más que suficiente.

Después instálate el plugin de Cloudinary para Wordpress, el cuál te permitirá seleccionar todas las imágenes de tu blog desde el panel de control de Wordpress y subirlas a Cloudinary, y el sólo las re-enlazará a la nueva dirección.

  • Selecciona el plan FREE y regístrate en Cloudinary

  • Dirígete al panel de control y busca la Enviroment variable que será del estilo a CLOUDINARY_URL=cloudinary://2497.... copialá para luego introducirla en el plugin. Fuente: Ghost for Beginners

  • Pega el código dentro de las opciones del plugin Fuente: Ghost for Beginners

  • Una vez instalado el plugin con la URL apuntando a tu Cloudinary, dirígete a tu libreria Media, selecciona todas tus imágenes y selecciona la acción Upload to Cloudinary Fuente: Ghost for Beginners

Migrar comentarios de Wordpress a Disqus

Ahora necesitamos salvar los comentarios de los posts. Si usas Disqus no hay problema porque al ser un servicio aparte, se mantienen aunque cambies el blog de sistema. Si no, esto es lo que puedes hacer:

Regístrate en Disqus y una vez registrado dirígete a la opción Add Disqus to site, añade un nuevo sitio y elige el código universal.

  • Add Disqus to Site

  • Añade la URL dónde estará alojado tu nuevo Blog

  • Elige el código universal

  • Copia el código para pegarlo en tu Theme de Ghost

Una vez hechos estos pasos, dirígete al template de tu Theme, en el caso del Theme por defecto (Casper), el archivo se encuentra en la ruta:

/ghost/content/themes/casper/post.hbs

Ábrelo con tu editor favorito, y busca el siguiente código:

<section class="post-content">  
    {{content}}
</section>  

Y justo debajo de {{content}} pega el código propocionado por Disqus.

Para migrar los comentarios de Wordpress a Disqus necesitamos el Plugin Disqus para Wordpress.

Instálalo y
1. clicka en Activate plugin
2. clicka en Configure
3. Logueate con tu nombre de usuario y contraseña de Disques
4. Selecciona el sitio que has creado en Disqus y clicka en Next
5. Clicka en Exports comments

Despues recibirás un email de Disqus cuando se haya completado la importación, ahi es cuando comenzarás a verlos en tu nuevo Ghost Blog.

Migrar el contenido de Wordpress a Ghost

Por fin, tras salvar las imágenes y comentarios, podemos por fin exportar el blog en el formato de Ghost. Necesitamos el plugin Ghost para Wordpress y clickar en la opción Download Ghost file

Fuente: Ghost for Beginners

Una vez descargado el fichero, vamos a importarlo en Ghost. Para ello en nuestro blog, nos dirigimos a Settings y la opción Lab.
En ella elegimos la opcón Import y seleccionamos el fichero que acabamos de crear

Para asegurarnos que todo se actualiza, es conveniente reiniciar el servicio que gestiona el blog. Y asei tendremos nuestros antiguos artículos de Wordpress, con sus imágenes y comentarios en el nuevo sistema de Ghost.
A Bloggear!!

Fuentes y más información:

Configura tu terminal de Mac como un desarrollador profesional

$
0
0

¿Quieres tener un flujo de trabajo que te permita ser ágil, ahorrar tiempo y ser más productivo en el desarrollo de tus proyectos? A continuación cuento una serie de aplicaciones y configuraciones que harán más agradable la jornada de trabajo en tu Mac. Hoy hablaremos de la terminal.

iTerm2

Mac OSX viene con un terminal por defecto, como todos los sistemas operativos, sin embargo en ocasiones se queda demasiado limitado. Tenemos una alternativa en Mac que se llama iTerm2. Es gratuita y podemos descargarla desde su página web.

Una de las cosas que más me gusta es la opción de ocultar y mostrar el terminal rápidamente con una combinación de teclas. Para configurar esta opción, debemos ir al menú iTerm2 > Preferences..., clickar en la pestaña Keys y habilitar el checkboxk Hotkey - Show/hide iTerm2 with a system-wide hotkey

Colores

También podemos configurar los colores que se muestran en la terminal, eligiendo unos que nos resulten agradables. Para ello en la ventana de preferencias elegimos la pestaña Profiles, nos creamos uno nuevo. En mi caso le he puesto mi nombre carlosazaustre y

Los predefinidos que usará el sistema son Black, Red, Green, Yellow, Blue, Magenta, Cyan y White. Podemos cambiar sus valores hexadecimales por otros que nos resulten más agradables.

Un Theme para iTerm que resulta cómodo para la vista a la hora de trabajar y pasar muchas horas en la pantalla es el conocido cómo Solarized Dark. Para añadir este theme a iTerm nos dirigimos al proyecto Solarized en Github y clickamos en la carpeta iterm2-colors-solarized. Elegimos el fichero Solarized Dark.itermscolors y pulsamos en RAW para ver su contenido en texto plano. Guardamos el fichero en nuestro equipo con extensión .itermcolors y lo importamos en iTerm, en la pestaña Profiles en el botón Load Presets... Una vez importado, lo seleccionamos en el menú desplegable para activarlo.

Shell

Lo más normal es que tu shell por defecto sea bash. Para comprobarlo solo tienes que escribir el siguiente comando en la terminal:

$ echo $SHELL

Que te responderá con

/bin/bash

Bash no está mal, pero prefiero utilizar zsh por las posibilidades y configuraciones que permite. Para cambiar el tipo de Shell en Mac. Abrimos el Panel de Preferencias del sistema, elegimos Usuarios y Grupos. Clickamos en nustro usuario con Click Derecho y elegimos Opciones avanzadas

En el campo Login Shell elegimos la opción /bib/zsh:

Tu terminal de iTerm lucirá ahora así:

Es el momento de personalizar el prompt por uno más Pro y útil que el que trae por defecto

Prompt

La fuente por defecto que trae iTerm es Monaco, que no está mal, pero yo últimamente prefiero la tipografía de Ubuntu. La podemos descargar desde font.ubuntu.com y una vez instalada la versión Monospace en nuestro sistema, la activamos desde la pestaña Text en el tab Profiles de las Preferencias de iTerm

Para poder cambiar el shell por defecto que trae zsh, por uno más personalizado, tenemos que editar el fichero .zshrc en el directorio home, o ~

Cargamos los colores de iTerm dentro de la configuración del fichero con autoload -U colors && colors.

Para personalizar el prompt usamos la variable PROMPT. Si escribimos algo como PROMPT=" > " en nuestro terminal tendremos algo como esto:

Podemos configurarlo con más información y colores para hacerlo más identificable.

  • La variable $fg[color] nos permite cambiar el color de lo que estamos escribiendo sustituyendo color por red, yellow, green, etc...
  • la variable %n nos devuelve el nombre del usuario del sistema, en mi caso carlosazaustre
  • %m nos devuelve el nombre de la máquina, en mi caso macbookpro.
  • %~ nos permite ver el directorio en el que nos encontramos.
  • %T nos devuelve el tiempo (hora:minutos) actual.
  • la variable $reset_color resetea los colores y vuelve a los de por defecto del terminal

También podemos crear funciones, por ejemplo la función precmd se ejecuta antes de cada Prompt, por lo tanto si creamos la siguiente función:

function precmd() {  
  ls
}

Se ejecutará el comando ls que lista los archivos del directorio en el que nos encontremos cada vez que ejecutemos un comando.

Tambien podemos crear alias para comandos, y así ahorrarnos escribir. Por ejemplo, podemos hacer que el comando ll sea el equivalente a ls -al para mostrar los ficheros de un directorio en 1 columna, incluyendo los archivos ocultos. Eso lo podemos hacer con la siguiente línea:
alias ll = 'ls -al'

Tambien es muy útilo para comandos de Git. podemos hacer los siguientes alias:

alias ga = 'git add'  
alias gc = 'git commit -m'  
alias gst = 'git status'  

Y a continuación unas funciones que te harán ahorra tiempo:

function take() {  
  mkdir $1
  cd $1
}

Ésta función lo que hace es crear un directorio con el nombre que le pasemos por parámetro ($1) y después dirigirse a ese directorio, algo así:

carlosazaustre@macbookpro ~/development  
> take project
carlosazaustre@macbookpro ~/development/project  

Y esta otra hará que te estalle la cabeza:

function server() {  
  if [ $1 ]
  then
    local port="$1"
  else
    local port="8000"
  fi
  open "http://localhost:$port" && python -m SimpleHTTPServer "$port"
}

Esto consigue que al teclear server en tu prompt, se arranque un servidor local en el directorio en que te encuentres y te abre el navegador para que puedas visualizarlo. Ideal para pruebas rápidas si no quieres configurar un servidor con Gulp o Grunt para tu entorno de desarrollo.

Mi fichero .zshrc completo, con lo que considero más útil, quedaría de la siguiente manera:

autoload -U colors promptinit && colors

# Quickly creates a folder
function take() {  
    mkdir $1
    cd $1
}

# Run a local server on current folder
function server() {  
    if [ $1 ]
    then
        local port="$1"
    else
        local port="8000"
    fi
    open "http://localhost:$port" && python -m SimpleHTTPServer "$port"
}

# Prompt
PROMPT="  
$fg[red]%n$reset_color@$fg[yellow]%m$reset_color: $fg[green]%~$reset_color
$fg[green]>$reset_color "

# alias
alias ll='ls -al'  
alias ga='git add'  
alias gc='git commit -m'  
alias gst='git status'  

Oh My ZSH

Si quieres ahorrarte tiempo y ampliar la funcionalidad de tu terminal, te aconsejo que instales Oh My ZSH, un framework para manejar la consiguración de tu shell.

Lo puedes instalar de la siguiente manera:

$ cd ~
$ curl -L http://install.ohmyz.sh | sh

Se instalará en el directorio ~/.oh-my-zsh.
Para configurar los themes, sólo tienes que abrir el fichero .zshrc que se ha sido sobreescrito, y en la línea 8: ZSH_THEME="nombre_del_theme_que_más_te_guste"
sustituir por el theme que más te guste.

A mi, particularmente me gusta este, nico.zsh-theme, que yo he cambiado un poco.

Copia el siguiente código en un fichero con nombre nico.zsh-theme en la carpeta ~/.oh-my-zsh/themes:

# fork from AVIT ZSH Theme

PROMPT='  
$(_user_host)${_current_dir}$(git_prompt_info)
$fg[yellow]>$reset_color '

PROMPT2='%{$fg[grey]%}◀%{$reset_color%} '

#RPROMPT='$(_vi_status)%{$(echotc UP 1)%}$(git_prompt_short_sha) $(_git_time_since_commit) ${_return_status} %T% %{$(echotc DO 1)%}'
RPROMPT='$(_vi_status)%{$(echotc UP 1)%}$(git_prompt_short_sha) ${_return_status} %T% %{$(echotc DO 1)%}'

local _current_dir="%{$fg[magenta]%}%0~%{$reset_color%} "  
local _return_status="%{$fg[red]%}%(?..⍉)%{$reset_color%}"  
local _hist_no="%{$fg[grey]%}%h%{$reset_color%}"

function _user_host() {  
  echo "%{$fg[red]%}%n%{$reset_color%}@%{$fg[yellow]%}%m%{$reset_color%}: "
}

function _vi_status() {  
  if {echo $fpath | grep -q "plugins/vi-mode"}; then
    echo "$(vi_mode_prompt_info)"
  fi
}

function _ruby_version() {  
  if {echo $fpath | grep -q "plugins/rvm"}; then
    echo "%{$fg[grey]%}$(rvm_prompt_info)%{$reset_color%}"
  fi
}

# Determine the time since last commit. If branch is clean,
# use a neutral color, otherwise colors will vary according to time.
function _git_time_since_commit() {  
  if git rev-parse --git-dir > /dev/null 2>&1; then
    # Only proceed if there is actually a commit.
    if [[ $(git log 2>&1 > /dev/null | grep -c "^fatal: bad default revision") == 0 ]]; then
      # Get the last commit.
      last_commit=$(git log --pretty=format:'%at' -1 2> /dev/null)
      now=$(date +%s)
      seconds_since_last_commit=$((now-last_commit))

      # Totals
      minutes=$((seconds_since_last_commit / 60))
      hours=$((seconds_since_last_commit/3600))

      # Sub-hours and sub-minutes
      days=$((seconds_since_last_commit / 86400))
      sub_hours=$((hours % 24))
      sub_minutes=$((minutes % 60))

      if [ $hours -gt 24 ]; then
          commit_age="${days}d"
      elif [ $minutes -gt 60 ]; then
          commit_age="${sub_hours}h${sub_minutes}m"
      else
          commit_age="${minutes}m"
      fi

      color=$ZSH_THEME_GIT_TIME_SINCE_COMMIT_NEUTRAL
      echo "$color$commit_age%{$reset_color%}"
    fi
  fi
}

if [[ $USER == "root" ]]; then  
  CARETCOLOR="red"
else  
  CARETCOLOR="white"
fi

MODE_INDICATOR="%{$fg_bold[yellow]%}❮%{$reset_color%}%{$fg[yellow]%}❮❮%{$reset_color%}"

ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[green]%}"  
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "

ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg[red]%}✗%{$reset_color%}"  
ZSH_THEME_GIT_PROMPT_CLEAN=" %{$fg[green]%}✔%{$reset_color%}"  
ZSH_THEME_GIT_PROMPT_ADDED=" %{$fg[green]%}✚{$reset_color%}"  
ZSH_THEME_GIT_PROMPT_MODIFIED=" %{$fg[yellow]%}⚑{$reset_color%} "  
ZSH_THEME_GIT_PROMPT_DELETED=" %{$fg[red]%}✖{$reset_color%} "  
ZSH_THEME_GIT_PROMPT_RENAMED=" %{$fg[blue]%}▴{$reset_color%} "  
ZSH_THEME_GIT_PROMPT_UNMERGED=" %{$fg[cyan]%}§{$reset_color%} "  
ZSH_THEME_GIT_PROMPT_UNTRACKED=" %{$fg[grey]%}◒{$reset_color%} "

# Colors vary depending on time lapsed.
ZSH_THEME_GIT_TIME_SINCE_COMMIT_SHORT="%{$fg[green]%}"  
ZSH_THEME_GIT_TIME_SHORT_COMMIT_MEDIUM="%{$fg[yellow]%}"  
ZSH_THEME_GIT_TIME_SINCE_COMMIT_LONG="%{$fg[red]%}"  
ZSH_THEME_GIT_TIME_SINCE_COMMIT_NEUTRAL="%{$fg[yellow]%}"

# Format for git_prompt_long_sha() and git_prompt_short_sha()
ZSH_THEME_GIT_PROMPT_SHA_BEFORE="%{$fg[white]%}[%{$fg[yellow]%}"  
ZSH_THEME_GIT_PROMPT_SHA_AFTER="%{$fg[white]%}]"

# LS colors, made with http://geoff.greer.fm/lscolors/
export LSCOLORS="exfxcxdxbxegedabagacad"  
export LS_COLORS='di=34;40:ln=35;40:so=32;40:pi=33;40:ex=31;40:bd=34;46:cd=34;43:su=0;41:sg=0;46:tw=0;42:ow=0;43:'  
export GREP_COLOR='1;33'  

Y en el fichero ~/.zshrc cambia el valor de la variable ZSH_THEME por nico:

ZSH_THEME="nico"  

Reinicia la terminal y tendrás el siguiente aspecto. Con feedback de la rama de Git en la que te encuentres, si ha habido cambios en el repositorio, etc...


Cómo relacionar tus modelos en MongoDB

$
0
0

MongoDB es una base de datos no relacional, es decir no es como las típicas bases de datos SQL (MySQL, Oracle, PostgreSQL, etc...) donde existen relaciones entre una tabla y otra. Veamos un ejemplo clásico.

Imaginemos una base de datos de libros. Tendríamos una tabla con los títulos de los libros y otra con los datos de los autores. El campo autor en la tabla de libros, apuntaría a un ID o clave primaria de un autor de la tabla autores.

En MongoDB podemos hacer algo parecido, por medio de referencias y el método populate de MongoDB.

Sigamos con el ejemplo anterior. Un modelo autor en Node.js usando mongoose sería tal que así:

var mongoose = require('mongoose');  
var Schema = mongoose.Schema;

var autorSchema = new Schema({  
    nombre: String,
    biografia: String,
    fecha_de_nacimiento: Date,
    nacionalidad: String
});

module.exports = mongoose.model('Autor', autorSchema);  

y supongamos un modelo sencillo para libro de la siguiente manera:

var mongoose = require('mongoose');  
var Schema = mongoose.Schema;  
var Autor = mongoose.model('Autor');

var libroSchema = new Schema({  
    titulo: String
    paginas: Number,
    isbn: String,
    autor: { type: Schema.ObjectId, ref: "Autor" } 
});

module.exports = mongoose.model("Libro", libroSchema);  

Si nos fijamos, para el campo autor en el modelo libro hemos usado el tipo Schema.ObjectId y la referencia al modelo Autor. Esto nos permitirá establecer la relación entre un campo de una tabla y otra.

Pero si no tenemos consultas SQL, y pedimos una lista de todos los libros en la base de datos ¿Qué datos nos llegarán?

Lo primero que programaríamos sería esto (en Express/Node.js):

app.get("/libros", function(req, res) {  
    Libro.find({}, function(err, libros) {
        res.status(200).send(libros)
    });
});

y si tenemos varios libros registrados en la base de datos, nos devolvería un JSON parecido a este:

[{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Juego de Tronos",
    "paginas": 150,
    "isbn": "0-553-57340-4", 
    "autor": "547db17cbe9958b000001"
},
{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Choque de Reyes",
    "paginas": 340,
    "isbn": "0-553-57340-5",
    "autor": "547db17cbe9958b000001"
},
{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Tormenta de Espadas",
    "paginas": 620,
    "isbn": "0-553-57340-7",
    "autor": "547db17cbe9958b000001"
}]

En el campo autor obtenemos la referencia en formato ObjectID del autor, pero no su ficha completa. ¿Qué pasa si queremos mostrar en un sólo JSON toda la información para poder pintarla de una sola llamada en nuestra webapp? Para eso necesitamos hacer uso del método populate de MongoDB que también implementa la librería mongoose.

En nuestro controlador anterior, debemos ampliarlo con lo siguiente:

app.get("/libros", function(req, res) {  
    Libro.find({}, function(err, libros) {
        Autor.populate(libros, {path: "autor"},function(err, libros){
            res.status(200).send(libros);
        }); 
    });
});

La línea Autor.populate(libros, {path: "autor"},...); toma el array de objectos libros y le indica que en la ruta autor lo "popule" con los datos del modelo Autor. Quedando una respuesta más completa como este ejemplo:

[{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Juego de Tronos",
    "paginas": 150,
    "isbn": "0-553-57340-4", 
    "autor": {
        "_id": "547db17cbe9958b000001",
        "__v": 0,
        "nombre": "George R. R. Martin",
        "biografia": "American novelist...",
        "fecha_de_nacimiento": "1948-09-20T00:00:00.000Z",
        "nacionalidad": "USA"
    }
},
{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Choque de Reyes",
    "paginas": 340,
    "isbn": "0-553-57340-5",
    "autor": {
        "_id": "547db17cbe9958b000001",
        "__v": 0,
        "nombre": "George R. R. Martin",
        "biografia": "American novelist...",
        "fecha_de_nacimiento": "1948-09-20T00:00:00.000Z",
        "nacionalidad": "USA"
    }
},
{
    "_id": "547db17cbe9956a000001",
    "__v": 0
    "titulo": "Tormenta de Espadas",
    "paginas": 620,
    "isbn": "0-553-57340-7",
    "autor": {
        "_id": "547db17cbe9958b000001",
        "__v": 0,
        "nombre": "George R. R. Martin",
        "biografia": "American novelist...",
        "fecha_de_nacimiento": "1948-09-20T00:00:00.000Z",
        "nacionalidad": "USA"
    }
}]

Podemos ver que el objeto _id del campo autor ha sido sustituido por el modelo autor completo al que hace referencia.

De esta manera conseguimos un comportamiento parecido al típico relacional en las bases de datos SQL en MongoDB.

Las métricas detrás de éste blog

$
0
0

Inicié ese blog a finales de septiembre de 2012 (Ha llovido desde entonces). Lo comencé para comentar un poco mi vida y mi día a día en Cork (Irlanda) donde estuve viviendo y trabajando remotamente como freelance durante una temporada. En inicio, el blog iba a ser inglés para obligarme a practicar, pero la pereza me pudo y escribía muy poco. Apenas escribí 4 post en los primeros 100 días de este blog.

Escribo este post para compartir como ha sido el crecimiento de este blog desde sus inicios en 2012 hasta finales de 2014. Me sirve para hacer retrospectiva y ver el resultado de un par de años de trabajo compartiendo tutoriales y ejemplos con la comunidad.

2012. Primeros 100 días

Como decía, los 100 primeros días de este blog, en 2012, pasaron sin pena ni gloria por el mundo de internet. Apenas 2 visitas al día de medía. Demasiado para 4 artículos que tenía el blog:

Hubo un pico de visitas el 26 de Noviembre, no recuerdo a que pudo ser debido, quizá porque lo compartí en Twitter o algo parecido.
En resumen, las métricas de los primeros 100 días de vida de carlosazaustre.es fueron estas:

Un vistazo a 2013. El primer año de vida del blog

Durante 2013 seguí en Irlanda hasta que llegaron los meses de verano. Después del verano estuve un mes de viaje por Estados Unidos y a continuación volví a España donde sigo viviendo a día de hoy.
En ese año escribí un total de 29 posts. Los primeros meses continué con la tendencia del anterior, apenas publicaba, Entre Enero y Abril escribí 4 posts y todos ellos en Inglés. A finales de Mayo le dí una vuelta de tuerca y comencé a escribir en castellano. Desde Mayo a finales de año escribí 25 posts, todos ellos relacionados con internet y la tecnología. Sin ninguna temática más concreta, aunque ya empecé a escribir algún tutorial.

Se puede ver en la gráfica, que hasta que no empecé a darle caña al blog (Meses de Junio y Julio sobre todo) no empezaron a llegar las visitas.

Ahi hay 2 picos importantes de tráfico. El primero de ellos es del 25 de Junio de 2013, por el post Camisetas Geeks para programadores con el que empecé a experimentar con Facebook Ads.

El siguiente pico llega el 2 de Agosto, otra fecha donde volví a iniciar una campaña, promocionando mis posts con Facebook Ads, sin invertir mucho dinero, tan solo para aprender y experimentar con la plataforma de anuncios de Facebook gastando menos de 25€.

Y el último pico de ese año fue el 8 de noviembre por el post Nuestro viaje por los Estados Unidos. Cómo viajar de forma más barata. Este totalmente orgánico a través de compartir en Twitter, Facebook y Google+.

En números, estan fueron las métricas del 2013, el primer año de vida del blog

2014. El año del despegue

Empecé 2014 con más interés en crear artículos y tutoriales para compartir conocimiento sobre la web. Sólo con las visitas de Enero y Febrero alcancé las totales de 2013. Durante el año pasado escribí 24 posts, 5 menos que en el año anterior, pero aún así las visitas fueron creciendo mes a mes debido imagino a que muchos de los artículos se han ido posicionando en Google gracias a vuestros comentarios, Retweets y Sharings en las redes sociales.

Se puede ver un pico de tráfico a mediados de Agosto de 2014, fue debido al lanzamiento del eBook de Angular, que se hizo un poco viral en Twitter y se consiguieron muchas descargas (más de 7000 hacia la fecha). En su lanzamiento podías conseguirlo por €2.40 o gratis si lo compartías en Twitter. Ahora lo puedes conseguir con un 30% de descuento sobre el precio original.

En esta tabla he recopilado las métricas mes a mes durante todo el año pasado:

A finales de Enero abrí una página en Facebook y comencé a subir algunos videotutoriales a mi canal de YouTube. De los Analytics de Facebook no tengo datos hasta Marzo, es por eso que no aparece ninguna cifra de Followers en ese campo.

Como puedes ver, mes a mes las visitas han ido aumentando, así como los suscriptores a la lista de correo, cuenta de twitter, canal de Youtube... Con constancia y dedicación se pueden llegar a conseguir muchas cosas :)

Si te lo propones, puedes conseguirlo todo - George McFly

¿Y en 2015?

Como dijo Uriel, uno de los Developer Advocate de Mejorando.la a finales del año pasado:

Este año no tengan propósitos, tengan Objectives Key Results (OKR)

Para el que no sepa que es un OKR, aquí te lo explican.

Uno de mis OKR de cara al 2015 es doblar las visitas mensuales, pasar de una media de 20.000 a 40.000. Creo que es ambicioso pero no por ello inlograble, teniendo en cuenta que ahora al mes este blog tiene el doble de visitas que todo el 2013 junto. Para conseguir eso debo proponerme y escribir más artículos de calidad, más tutoriales y videotutoriales y crear más recursos, como por ejemplo otro eBook que tengo en mente y alguna cosillas más.

También es importante el tiempo de carga de la página. Por eso uno de los primeros pasos que he dado este año es cambiar el motor del blog de Wordpress y migrarlo a Ghost. Ahora realiza menos operaciones y consultas y no carga tantos plugins como tenía mi anterior theme de Wordpress. También he pasado de un hosting compartido a un servidor virtual en DigitalOcean. El Theme está basado en Velox, un Theme desarrollado por David Rey Acosta que tiene muy buenos PageSpeed Insights

¿Qué quiero decir con esto? Los datos hablan por si solos:

Esto parece una tontería, pero la reducción del tiempo de carga, además de evitar que los lectores abandonen la lectura, mejora el posicionamiento en Google, así que es bueno tenerlo en cuenta ;)

¡Vamos a por el 2015!

¿Carreteras? ¿Dónde vamos no necesitamos... carreteras

Libro "Desarrollo Web Ágil con Angular.js"

$
0
0

Hazte con uno de los libros sobre desarrollo web con Angular.js más descargados en español. Con más de 7000 descargas en España y Latinoamérica.

Con él aprenderás buenas prácticas en el desarrollo de aplicaciones web con el framework de JavaScript Angular.js y aprenderás a automatizar tus tareas cotidianas en el Frontend con Gulp.js, para ser más productivo y ágil.


Disponible en 3 formatos

ePub PDF Mobi
Formato ePub Formato PDF Formato Mobi
Comprar Ahora Comprar Ahora Comprar Ahora

Tabla de Contenidos:

  1. Introducción
    1. Estructura de una aplicación web moderna
    2. Tecnologías
  2. Configuración del entorno de trabajo
    1. Instalar Google Chrome
    2. Instalar y configurar SublimeText2 o Atom
    3. Instalar y configurar iTerm2
    4. Instalar Git
      1. Registro en GitHub
      2. Registro en GitLab
    5. Estructura de directorios y ficheros
  3. Automatizando nuestro flujo de trabajo
    1. Anatomía de una aplicación Angular JS
    2. HTML5Boilerplate
    3. Instalando dependencias
    4. Módulos de la aplicación
    5. Arquitectura
      1. Principal scripts/app.js
      2. Servicios scripts/services.js
      3. Controladores scripts/controllers.js
      4. Vistas parciales
  4. Diseño con preprocesadores CSS
    1. Fontawesome
    2. Fuentes Tipográficas
    3. Estilos de la Aplicación
  5. Optimizando para Producción
    1. Cacheado de plantillas
    2. Concatenación de ficheros JS y CSS
    3. Servidor de archivos de producción
    4. Reducción de código CSS

Los lectores opinan

Ya voy por la Pagina 54 del Ebook. Justo lo que se espera. Bastante adictivo y muy Profesional

- Yonaides Tavares @yonaides

Miren que @carlosazaustre se hizo una muy bonita guia de angular.js

- Diana Reyes @tifis

Excelente libro!!! muchas gracias por el aporte! Saludos desde Argentina :)

- Adrián Rojas @rojasadrian_e

El precio, lo mejor!

- Richard Castillo @rOxhh

Curioso ebook para los que estamos empezando con AngularJS

- Vicente Pons @GpoNsU

Cómpralo ahora

ePub PDF Mobi
Formato ePub Formato PDF Formato Mobi
Comprar Ahora Comprar Ahora Comprar Ahora

Detalles Técnicos

  • 62 páginas
  • Precio: €2,40 (30% DTO. si compartes en redes sociales)
  • Formato PDF, ePub y Mobi
  • Idioma Español (Castellano)
  • Fecha de publicación:
    • 2a Edición: Enero de 2015
    • 1a Edición: Agosto de 2014

H4ckademy. Open School para aprender a base de proyectos

$
0
0

H4ckademy es el proyecto que está llevando a cabo un buen amigo, Israel Gutierrez (@gootyfer). Quiere traer a Europa (Empezando por Madrid en España) la esencia de la Hacker School que funciona actualmente en New York y el espíritu de Google Summer of Code.

Se trata de una escuela de currículum abierto. Durante 6 semanas, Los desarrolladores que sean elegidos para participar en el primer batch, mejorarán sus habilidades como programadores colaborando en proyectos Open Source en un espacio de coworking.

Curriculum abierto quiere decir que no vas a aprender una tecnología o metodología concreta, no hay asignaturas ni "deberes". Los alumnos únicamente han de llegar con unos objetivos de aprendizaje como puede ser mejorar la calidad del código, aprender a hacer tests, aprender un nuevo framework o lenguaje, etc. Se trabaja por proyectos, no por clases y el alumno es el que elige el proyecto de acuerdo a sus objetivos.

A cambio, H4ckademy pone facilitadores a disposición de los alumnos para guiarles día a día en sus objetivos, además del ambiente de trabajo e iniciativa que se podrá respirar allí junto con otros compañeros con las mismas inquitudes que tú. Los falcilitadores proporcionarán a los alumnos conocimientos en diseño, programación y tratamiento de datos.

H4ckademy es totalmente gratuito para los participantes. Se trata de un programa inmmersivo en un espacio de trabajo aún por confirmar. El programa se inicia el próximo 16 de Febrero y para poder inscribirte en us proceso de selección debes darte prisa, ya que el plazo de solicitudes se cerrará este mismo sábado.

Los únicos requisitos para participar son tener una experiencia previa en programación (no tienes que ser NinjaRockStar, con tener ciertos conocimientos básicos es suficiente) y poder dedicar 6 semanas a full-time.

Si quieres más información acerca de este interesantísimo proyecto, te remito a su página web y a su blog. También tienes disponible la entrevista que hicieron a Israel Gutierrez sobre el proyecto en el blog de GenbetaDev.

Aprende ECMAScript 6, el nuevo estándar de JavaScript

$
0
0

ECMAScript v6 (o ES6) es el estándar que seguirá JavaScript a partir de Junio de este año (2015). Hasta el momento la versión de JS que estamos usando en nuestros navegadores y Node.js, es la v5.

La evolución de JavaScript

Primero un poco de historia. En 1995 (hace 20 años!) Brendan Eich crea un lengujea llamado Mocha cuando trabajaba en Netscape. En Septiembre de ese año lo renombra a LiveScript hasta que le cambiaron el nombre a JavaScript debido a una estrategia de marketing, ya que Netscape fue adquirida por Sun Microsystems, propietaria del lenguaje Java, muy popular por aquel entonces.

¡Advertencia!: aclarar lo siguiente Java != JavaScript.

En 1997 se crea un comité (TC39) para estadarizar JavaScript por la European Computer Manufacturers' Association, ECMA. Se diseña el estándar del DOM (Document Object Model) para evitar incompatibilidades entre navegadores. A partir de entonces los estándares de JavaScript se rigen por ECMAScript.

historia de JavaScript

En 1999 aparece la 3a versión del estándar ECMAScript, que se mantendría vigente hasta hace pocos años. Hubo pequeños intentos de escribir la versión 4, pero hasta 2011 no se aprobó y se estandarizó la versíon 5 (ES5) que es la que usamos hoy en día.

historia de javascript

En junio de 2013 quedó parado el borrador de la versión 6, pero en Diciembre de 2014 se aprobó al fin y se espera su estandarización a partir de Junio de 2015.

Principales novedades de ES6

ES6 trae muchos cambios significativos al lenguaje. Veamos algunos de ellos:

Función Arrow

¿Cuántas veces has programado un código con una estructura similar a la siguiente?

// ES5
// Imaginemos una variable data que incluye un array de objectos
var data = [{...}, {...}, {...}, ...];  
data.forEach(function(elem){  
    // Tratamos el elemento
    console.log(elem)
});

Con la función arrow => de ES6, el código anterior se sustituiría por:

//ES6
var data = [{...}, {...}, {...}, ...];  
data.forEach(elem => {  
    console.log(elem);
});

Mucho más limpio y claro. CoffeeScript (un metalenguaje que compila a JavaScript) usa algo parecido.

Incluso la podemos utilizar así:

// ES5
var miFuncion = function(num) {  
    return num + num;
}
// ES6
var miFuncion = (num) => num + num;  

Clases

Ahora JavaScript tendrá clases, muy parecidas las funciones constructoras de objectos que realizabamos en el estándar anterior, pero ahora bajo el paradigma de clases, con todo lo que eso conlleva, como por ejemplo, herencia.

class LibroTecnico extends Libro {  
    constructor(tematica, paginas) {
        super(tematica, paginas);
        this.capitulos = [];
        this.precio = "";
        // ...
    }
    metodo() {
        // ...
    }
}

This

La variable this muchas veces se vuelve un dolor de cabeza. antíguamente teníamos que cachearlo en otra variable ya que solo hace referencia al contexto en el que nos encontremos. Por ejemplo, en el siguiente código si no hacemos var that = this dentro de la función document.addEventListener, this haría referencia a la función que pasamos por Callback y no podríamos llamar a foo()

//ES3
var obj = {  
    foo : function() {...},
    bar : function() {
        var that = this;
        document.addEventListener("click", function(e) {
            that.foo();
        });
    }
}

Con ECMAScript5 la cosa cambió un poco, y gracias al método bind podíamos indicarle que this hace referencia a un contexto y no a otro.

//ES5
var obj = {  
    foo : function() {...},
    bar : function() {
        document.addEventListener("click", function(e) {
            this.foo();
        }.bind(this));
    }
}

Ahora con ES6 y la función Arrow => la cosa es todavía más visual y sencilla.

//ES6
var obj = {  
    foo : function() {...},
    bar : function() {
        document.addEventListener("click", (e) => this.foo());
    }
}

let y const

Ahora podemos declarar variables con let en lugar de var si no queremos que sean accesibles más allá de un ámbito. Por ejemplo:

//ES5
(function() {
    console.log(x); // x no está definida aún.
    if(true) {
        var x = "hola mundo";
    }
    console.log(x); 
    // Imprime "hola mundo", porque "var" hace que sea global
    // a la función;
})();

//ES6
(function() {
    if(true) {
        let x = "hola mundo";
    }
    console.log(x); 
    //Da error, porque "x" ha sido definida dentro del "if"
})();

Ahora con const podemos crear constantes que sólo se puedan leer y no modificar a lo largo del código. Veamos un ejemplo

(function() {
    const PI;
    PI = 3.15; 
    // ERROR, porque ha de asignarse un valor en la 
    // declaración
})();

(function() {
    const PI = 3.15;
    PI = 3.14159;
    // ERROR de nuevo, porque es sólo-lectura
})();

Template Strings

Con ES6 podemos interpolar Strings de una forma más sencilla que como estábamos haciendo hasta ahora. Fíjate en este ejemplo:

//ES6
let nombre1 = "JavaScript";  
let nombre2 = "awesome";  
console.log("Sólo quiero decir que ${nombre1} is ${nombre2}");  
// Solo quiero decir que JavaScript is awesome

También podemos tener String multilínea sin necesidad de concatenarlos con +.

//ES5
var saludo = "ola " +  
"que " +
"ase ";

//ES6
var saludo = "ola  
que  
ase";

console.log("hola  
que  
ase");  

Destructuring

Tenemos nuevas formas de asignar valores a Arrays y a Objetos. Veamos unos ejemplos

var [a, b] = ["hola", "mundo"];  
console.log(a); // "hola"  
console.log(b); // "mundo"

var obj = { nombre: "Carlos", apellido: "Azaustre" };  
var { nombre, apellido } = obj;  
console.log(nombre); // "Carlos"  

¿No te ha estallado el cerebro todavía? Pues mira esto:

var foo = function() {  
    return ["175", "75"];
};
var [estatura, peso] = foo();  
console.log(estatura); //175  
console.log(peso); //75  

Mind Blow

Valores por defecto

Otra novedad es asignar valores por defecto a las variables que se pasan por parámatros en las funciones. Antes teníamos que comprobar si la variable ya tenía un valor. Ahora con ES6 se la podemos asignar según creemos la función.

//ES5
function(valor) {  
    valor = valor || "foo";
}

//ES6
function(valor = "foo") {...};  

Módulos

A esto lo llamo un browserify nativo. Ahora JavaScript se empieza a parecer a lenguajes como Python o Ruby. Llamamos a las funciones desde los propios Scripts, sin tener que importarlos en el HTML, si usamos JavaScript en el navegador.

//File: lib/person.js
module "person" {  
    export function hello(nombre) {
        return nombre;
    }
}

También se puede exportar así, según una aclaración de Sergio Daniel Xalambrí

export function hello(nombre) {...}; o también, si solo es una función la que tiene el módulo: export default function(nombre) {...};

Y para importar en otro fichero:

//File: app.js
import { hello } from "person";  
var app = {  
    foo: function() {
        hello("Carlos");
    }
}
export app;  

Empieza a usar ES6 hoy mismo

Todo esto es muy bonito, pero ¿Cómo podemos empezar a utilizarlo hoy en día?. Lo primero más recomendable es que te instales la última versión de Chrome, que es uno de los navegadores que está implementando las nuevas features de ES6 más rápidamente. Te aconsejo incluso que instales Chrome Canary, que es la versión de Chrome que prueba funcionalidades antes de lanzarlas en el Chrome original.

Para probar directamente código ES6 en la consola de tu navegador. Escribe en la barra de direcciones chrome://flags y tendrás una página como ésta:

Chrome Flags

Y activar el flag Enable Experimental JavaScript.

Esto te permitirá probar algunas features pero no todas porque aún están en desarrollo.

La otra opción, más extendida, es escribir en ES6 en tus ficheros JavaScript y después "compilarlos" a la versión ES5. Existen herramientas como 6to5 que te permiten lograrlo.

Esto sería un ejemplo de Gulpfile con un plugin de 6to5 que nos "compila" a ES5 y así poder usarlo en el navegador:

$ npm install --save-dev gulp-6to5
var gulp = require("gulp");  
var to5 = require("gulp-6to5");

gulp.task("default", function() {  
    return gulp.src("scripts/app.js");
        .pipe(to5())
        .pipe(gulp.dest("dist"));
});

Ésto es solo el principio, recuerda que el estándar fue aprobado en diciembre y empezará a implantarse en Junio de este año. Pero no está mal prepararse para lo que viene. Por ejemplo, AngularJS 2.0 se está reescribiendo en ES6 o IO.js (el fork de Node.js) utiliza ES6 y puedes usar las features en el servidor

ES6 next stop


Para indagar más, estás son las fuentes de este artículo:

Mi experiencia como profesor en Platzi

$
0
0

Viaje a Bogotá

Durante esta semana (del 8 al 14 de Febrero) he sido uno de los profesores del Curso de Desarrollo Web que ofrece Platzi (Antes Mejorando.la). Para ello he viajado a Bogotá (Colombia) a las oficinas y estudios centrales de Platzi.

Vistas de Bogotá desde la oficina más cool de Colombia

Ha sido una semana muy intensa y a la vez muy gratificante y llena de experiencias.

Conocí los cursos de Platzi a principios de 2013, hace ya 2 años y desde entonces soy un adicto a todo el material que producen, ya sea su blog, su canal de Youtube, su Live de los jueves y sobre todo, sus cursos online.

Freddy, CEO de Platzi, me contactó hace un tiempo y fue todo un honor que pensara en mi para ser profesor del nuevo curso de desarrollo web, compartiendo "tutela" con un genio como es Daniel Martínez (@Wakkos).

Entre los dos hemos enseñado HTML5, CSS3 y JS básico para que puedas crear tu propia web desde cero. Por mi parte, me he encargado de enseñar JavaScript, jQuery y algunos elementos cool de HTML5 como Geolocation y LocalStorage para crear una aplicación web.

Team video listos para el Streming

Clases en vivo

Debo confesar que los primeros días estaba nervioso. Nunca había dado un curso online en directo y no sabía muy bien como iba a salir. Si que tenía experiencia grabando videotutoriales y algún que otro "Comunidad Platzi" pero el directo de una clase online en vivo, no lo había vivido aún.

Minutos antes de la última clase en vivo.

Y la verdad es que me encontré muy cómodo, pero sobre todo gracias al equipo que hay detrás de los streamings y que no se ve, pero sin ellos no habría nada. Entre ellos Carlos Paredes y las nuevas incorporaciones como Ángel Montalbán y Winiberto, con los que durante esta semana he compartido trabajo, risas y convivencia las 24h del día y ya los considero familia :)

Win y Ángel en pleno Live

Las clases eran de 1:00 a 3:00 de la tarde y de 8:00 a 10:00 de la noche en Horario de Colombia. Los días de curso salíamos tarde de la oficina. Acababa el día destrozado pero muy contento. Despues del descanso necesario, siempre volvía con ganas a la PlatziOficina a dar la siguiente clase.

Team Platzi

Costó acostumbrarse al JetLag pero gracias al Team siempre había algo que hacer y los días fueron muy intensos haciéndome olvidar de la hora que era.

ArepaJS

No puedo dejarme al equipo de Devs. Auténticos profesionales y mejores personas. He pasado muy buenos momentos con ellos. Compartiendo charlas de JavaScript con Diego Uribe y Leonidas Esteban, auténticos ninjas del JS. Y aprendiendo a bloquear mi laptop gracias a Yohan y Victor, para evitar que me "Bartearan" xD

De igual manera el equipo de diseño son unos artístas y gente increible. Conocer a la gente detrás de la imagen de Platzi: Carlos Vaca, Jennifer y Santiago Eastman ha sido un honor.

The Platzi Men

No me olvido del resto del Team, Sergio Zafra, Aleyda, Cesar, Alejandro, Doña Araceli, y sobre todo de Nicole, Relationship Manager de Platzi y un encanto de persona a la vez que trabajadora. Si el día tuviera 30horas, ella trabajaría 32, siempre atenta a que todos estuviesemos bien.

Poder ser parte de Platzi durante una semana, vivir cómo es la grabación de un Live y las clases de comunidad, son cosas que me llevo conmigo y que me han enseñado todo el trabajo que hay detrás de cada material que se publica en Platzi y que no vemos.

Selfie-Comunidad Platzi

A Freddy ya le conocí de una vista relámpago que hizo a Madrid, pero me quedo sin conocer personalmente, Christian, Juan Pablo y Mike. Pero estoy seguro que nuestros caminos se cruzarán de nuevo y tendremos esa oportunidad.

¡Gracias Team!

El camino para ser un Pro en JavaScript

$
0
0

Haz lo que te motive.

Nada resulta más reconfortante y productivo que dedicar tu tiempo a algo que te guste. Si te aburre desarrollar un tipo de Software, busca otro tipo que te motive, puede ser otra plataforma, otro lenguaje,...

Yo estuve un tiempo trabajando de programador en empresas, donde no había lugar para la creatividad, desarrollando software que no me motivaba, con lenguajes que no me resultaban prácticos, etc. Eso hace que te desanimes y llegues a odiar tu profesión.

Plantéate un cambio de aires. Prueba un nuevo lenguaje, ese nuevo framework del que has oído hablar, esa nueva plataforma que tanto está en boca de todos... Rétate a ti mismo. Despejarás tu mente de la rutina y aprenderás algo nuevo. Salir de tu zona de comfort siempre es una experiencia enriquecedora.

JavaScript, un lenguaje para dominarlos a todos.

Un lenguaje para dominarlos a todos

Como lenguaje a aprender y profesionalizarme, yo me decanté por JavaScript. Me llamó mucho la atención Node.js. JavaScript siempre ha sido el lenguaje que daba dinamismo y añadía efectos a las páginas web. Que ese lenguaje haya sido llevado al servidor y permitiera servir páginas web, conectar con bases de datos, etc... me pareció sorprendente.

Eso fue lo que hizo que invirtiera mi tiempo en conocer más en profundidad este lenguaje. Y elegí un buen momento. Hasta ese instante los frameworks y librerías más conocidas y usadas eran jQuery y BackboneJS, pero rápidamente empezaron a surgir nuevos frameworks como AngularJS, EmberJS, Ionic, etc... que enriquecían el ecosistema.

Hoy en día es increible la de cosas que se pueden usar con JavaScript, incluso es posible programar microcontroladores como Tessel con JavaScript. Awesome

La web es tu fuente de conocimiento.

Internet es la universidad del desarrollador. Quizá otras titulaciones aún necesiten de una facultad para aprender y ser un profesional en su campo, pero el sector de la programación puede ser aprendido y practicado 100% en Internet.

Cuando descubrí los MOOCs (Massive Open Online Courses) me estalló el cerebro. Cuando estudiaba en la universidad, si quería asistir a una clase magistral tenía que ser presencial, tenía que tomar apuntes corriendo y no podía dar marcha atrás si no comprendía el concepto que el profesor te daba. La mayoría de los profesores no se toman en serio sus clases, porque se dedican a otras cosas, y eso hace que la calidad de la clase sea mala. Las únicas referencias que podías consultar para aumentar conocimiento eran los libros de la biblioteca. La gran mayoría desactualizados.

Con los MOOCs todo eso cambió. Puedes acceder a miles de videos de clases de todo el mundo. No necesitas matricularte en Stanford para asisitir a una clase magistral de la universidad. Con YouTube lo tienes. Los formadores, al estar expuestos a una audiencia mucho mayor que el aula de una clase tradicional, se esfuerzan más y sus clases son de mayor calidad, ya que si el profesor no te transmite ningún conocimiento seguramente su curso no sea valorado por la gente y no se dará a conocer.

Platzi

Comencé con Coursera y posteriormente conocí Mejorando.la (ahora Platzi). Si quieres aprender JavaScript son muy recomendables para iniciarte y conocer las bases y buenas prácticas de mano de profesionales que se dedican a ello.

Mi primer curso fue el de diseño web básico y posteriormente el de Frontend con un nivel intermedio. Actualmente, si quieres profesionalizarte en la web, te recomiendo que inicies con su curso básico de programación, que es totalmente gratis, y te enseña bases de JavaScript y cosas bastante chulas y avanzadas para ser un curso básico como son Canvas y programar drones con JavaScript.

Posteriormente te recomiendo el de diseño y desarrollo web básico para conocer HTML, CSS y JavaScript más en profundidad. De seguido prueba con el de Frontend Profesional y aprende preprocesadores de CSS, frameworks de JavaScript, gestores de tareas, etc.

Si quieres ser un full-stack y dominar tanto el frontend como el backend, aprovecha tu suscripción mensual y toma el curso de Backend. Tiene un apartado de Node.js pero se centra más en Django y Ruby on Rails. No está de mal conocer patrones de diseño en el backend aunque luego usemos otro lenguaje.

Y por último el curso profesional de JavaScript y Node.js para aprender a utilizar JavaScript de principio a fin.

Lee.

Leer es muy importante. Nos mantiene el cerebro en funcionamiento y nos despierta la creatividad. Lee libros técnicos. Se que la mayoría están en inglés y no hay muchos en español. A mi eso también me frustraba, pero hay que invertir tiempo en aprender inglés. Si te dedicas a la web y no sabes inglés, al menos a nivel de lectura, es muy costoso aprovechar los conocimientos que internet nos brinda. Hasta hace un par de años yo era incapaz de leer un libro en inglés, tardaba mucho y acababa distrayéndome y perdiéndome. Como mucho leía algun blogpost en inglés pero nada más.

Hace un par de años me propuse leer al menos un libro en inglés al més y comencé a notar como mejoraba mi entendimiento en ese lenguaje. Es un proceso lento, pero llega un momento en el que lees inglés como si leyeras castellano. Recomiendo hacer este esfuerzo, merece la pena y descubres un mundo nuevo de conocimiento que antes tenías cerrado.

Eloquent JavaScript

Si quieres expandir tus conocimientos sobre JavaScript, hay muchos libros. Los que más me gustaron y recomiendo los recopilé en un antiguo post que puedes consultar aquí.

Y si quieres aprender AngularJS para utilizarlo en tus proyectos, te recomiendo mi libro en español :)

Desarrolla proyectos propios.

Puedes hacer todos los cursos de Platzi, Code School, Codeacademy, Coursera, etc.. Tendrás mucho conocimiento adquirido y unas bases muy profundas, pero para probarlas tienes que desarrollar algo por tu cuenta.

Cuando empieces un proyecto personal te encontrarás con errores e incógnitas que no se han dado en los cursos, porque serán muy específicos de lo que estás desarrollando. No tienes que desarrollar la próxima Startup del Billón de dólares, empieza haciendo un clon de algo que ya exista, por ejemplo, un clon de Twitter, un clon de Instagram, un clon de Youtube. Así aprenderás que problemas pueden presentársete e intentar resolverlos.

Imagina que estás haciendo un clon de Instagram con Node.js y AngularJS, en algún momento vas a querer programar la subida de una foto al servidor. Seguramente en ningún curso te han dado una lección de "Cómo subir una foto desde Angular.js con tu API REST en Node.js a un bucket de Amazon S3", como mucho habrás visto como enviar ficheros por formulario, o como hacer un API REST en Node.js, pero no el caso concreto.

Es tu tarea en ese momento, buscar en Google. Tienes numerosos tutoriales de personas que se han encontrado con el mismo problema que tu y lo han compartido con la comunidad. Visita StackOverflow, seguramente hay alguien que ha tenido tu misma duda y otra presona lo ha resuelto. Paséate por GitHub o NPM, aprende de los proyectos Open Source que la comunidad desarrolla, aprenderás buenos tips, librerías, formas de programar, que te harán crecer como profesional.

Únete a comunidades de desarrolladores.

No te quedes sólo casa, sal afuera y conoce gente. En internet tenemos muchas comunidades donde conocer gente con nuestras mismas inquietudes y gustos. Si eres estudiante de Platzi, tienes Comunidad Platzi, donde miles de estudiantes y profesionales de toda Latinoamérica y España están ahí compartiendo conocimiento y dudas. En Meetup puedes buscar grupos de desarrolladores en tu ciudad. En Madrid tenemos NodeJSMadrid, MadridJS, WebRTC Madrid, AngularJS Madrid, Python Madrid, Polymer Madrid, MongoDB User Group... Seguramente en tu ciudad hay un grupo de meetup que se reúne de vez en cuando y la temática es tu lenguaje favorito. Y si no lo hay, ¡Créalo! seguramente hay más gente como tu que aún no se ha atrevido a dar el paso.

Otra alternativa son los Hackthones. Programar una aplicación en menos de un día en equipo y poder ganar premios. ¿Conoces Hackathon Lovers?

También tenemos Betabeers, que está presente en varias ciudades de España. En el puedes presentar los proyectos que estás desarrollando, ya sea una Startup, una librería que has conocido recientemnte o un framework que estés desarrollando. De esta manera conoces más gente como tú y lo más importante, te das a conocer.

De igual manera, existen los Google Developer Group, presentes en más de 100 países y 600 ciudades, donde, al igual que en Meetup, se reúnen desarrolladores que utilizan tecnologías de Google, como pueden ser Android, Polymer, Angular, Google Cloud, etc. La oferta es impresionante.

Comparte tu conocimiento.

Todo lo que aprendas, compártelo. De igual manera que cuando tienes un error en tu aplicación y lo buscas en Google o directamente en Stackoverflow y alguien ya lo ha solucionado, se tú la persona que lo solucione y ayuda a otros. Comparte tutoriales y ejemplos de lo que haces. Abre un blog como este y comparte tu conocimiento. La web la hacemos nosotros y el contenido que encotramos en ella está redactado por personas como nosotros. Se parte de ello, te hará mejorar y crecer como profesional.



¿Quieres más? Hazte con mi ebook en español sobre desarrollo web ágil con AngularJS y GulpJS.


¿Qué es la autenticación con Token?

$
0
0

Existen varios sistemas de autenticación en una aplicación web

Autenticación en el servidor, almacenando la sesión

El más común hasta ahora era el que guardaba en una sesión la información del usuario. Para ello necesitábamos almacenar esa información en una base de datos, podía ser una colección de MongoDB o en Redis.

Sin embargo esto suponía una pérdida de escalabilidad en nuestra aplicación, ya que el servidor debe almacenar un registro por cada vez que el usuario se autentique en el sistema. Además hacemos que el Backend se encargue de ello y de esta manera si queremos desarrollar una aplicación móvil, necesitaríamos otro backend diferente, no pudiendo reutilizarlo.

Autenticación sin estado con Tokens

Por ello una de las nuevas tendencias en cuanto al desarrollo web moderno se refiere, es la autenticación por medio de Tokens y que nuestro backend sea un API RESTful sin información de estado, stateless.

El funcionamiento es el siguiente. El usuario se autentica en nuestra aplicación, bien con un par usuario/contraseña, o a través de un proveedor como puede ser Twitter, Facebook o Google por ejemplo. A partir de entonces, cada petición HTTP que haga el usuario va acompañada de un Token en la cabecera. Este Token no es más que una firma cifrada que permite a nuestro API identificar al usuario. Pero este Token no se almacena en el servidor, si no en el lado del cliente (por ejemplo en localStorage o sessionStorage) y el API es el que se encarga de descrifrar ese Token y redirigir el flujo de la aplicación en un sentido u otro.

Como los tokens son almacenados en el lado del cliente, no hay información de estado y la aplicación se vuelve totalmente escalable. Podemos usar el mismo API para diferentes apliaciones (Web, Mobile, Android, iOS, ...) solo debemos preocuparnos de enviar los datos en formato JSON y generar y descrifrar tokens en la autenticación y posteriores peticiones HTTP a través de un middleware.

También nos añade más seguridad. Al no utilizar cookies para almacenar la información del usuario, podemos evitar ataques CSRF (Cross-Site Request Forgery) que manipulen la sesión que se envía al backend. Por supuesto podemos hacer que el token expire después de un tiempo lo que le añade una capa extra de seguridad.

JSON Web Tokens

El estándar para este tipo de autenticación es utilizar JSON Web Tokens (JWT). Al igual que los APIs, el formato JSON es agnóstico del lenguaje, y podemos utilizar el que queramos (Node.js, Python, Ruby, PHP, .NET, Java,...)

El formato de un JWT está compuesto por 3 strings separados por un punto . algo así como:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NGE4Y2U2MThlOTFiMGIxMzY2NWUyZjkiLCJpYXQiOiIxNDI0MTgwNDg0IiwiZXhwIjoiMTQyNTM5MDE0MiJ9.yk4nouUteW54F1HbWtgg1wJxeDjqDA_8AhUPyjE5K0U  

Cada string significa una cosa:

  • Header La primera parte es la cabecera del token, que a su vez tiene otras dos partes, el tipo, en este caso un JWT y la codificación utilizada. Comunmente es el algoritmo HMAC SHA256, El contenido sin codificar es el siguiente:
{
    "typ": "JWT",
    "alg": "HS256
}

Codificado sería: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

  • Payload EL Payload está compuesto por los llamados JWT Claims donde irán colocados la atributos que definen nuestro token. Exiten varios que puedes consultar aquí, los más comunes a utilizar son:
    • sub: Identifica el sujeto del token, por ejemplo un identificador de usuario.
    • iat: Identifica la fecha de creación del token, válido para si queremos ponerle una fecha de caducidad. En formato de tiempo UNIX
    • exp: Identifica a la fecha de expiración del token. Podemos calcularla a partir del iat. También en formato de tiempo UNIX.
{
    "sub": "54a8ce618e91b0b13665e2f9",
    "iat": "1424180484",
    "exp": "1425390142"
}

También podemos añadirle más campos, incluso personalizados, como pueden ser el rol del usuario, etc.

{
    "sub": "54a8ce618e91b0b13665e2f9",
    "iat": "1424180484",
    "exp": "1425390142",
    "admin": true,
    "role": 1
}

Codificado sería: eyJzdWIiOiI1NGE4Y2U2MThlOTFiMGIxMzY2NWUyZjkiLCJpYXQiOiIxNDI0MTgwNDg0IiwiZXhwIjoiMTQyNTM5MDE0MiJ9

  • Signature La firma es la tercera y última parte del JSON Web Token. Está formada por los anteriores componentes (Header y Payload) cifrados en Base64 con una clave secreta (almacenada en nuestro backend). Así sirve de Hash para comprobar que todo está bien.
HMACSHA256(  
    base64UrlEncode(header) + "." + 
    base64UrlEncode(payload), secret
);

Codificado sería: yk4nouUteW54F1HbWtgg1wJxeDjqDA_8AhUPyjE5K0U

Por tanto, todo nuestro JSON Web Token, una vez codificado tendrá esta pinta:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI1NGE4Y2U2MThlOTFiMGIxMzY2NWUyZjkiLCJpYXQiOiIxNDI0MTgwNDg0IiwiZXhwIjoiMTQyNTM5MDE0MiJ9.yk4nouUteW54F1HbWtgg1wJxeDjqDA_8AhUPyjE5K0U  

Que si lo comprobamos en la web JWT.io vemos que nos lo traduce a los campos que hemos visto.

Más adelante, en este blog, veremos como realizar la autenticación con Token en el servidor y en el frontend usando Node.js y AngularJS.

Autenticación con Token en Node.js

$
0
0

En el anterior post vimos las bases de la autenticación basada en token en una aplicación web. En este post, vamos a ver como implementar este tipo de autenticación en un servidor usando Node.js

Voy a separar las funciones en varios archivos, siguiendo buenas prácticas y modularizando dependendiendo de la funcionalidad.

Nuestro servidor en Node.js

Lo primero es crear el archivo server.js dónde configuramos Express (en versión 4), importamos los módulos necesarios y hacemos correr el servidor y la base de datos.

Si te pierdes un poco, en éste post anterior expliqué como crear un API REST en Node.js con Express y MongoDB. Y si prefieres también tengo un videotutorial en YouTube sobre el tema.

Configuración básica de un servidor en Node.js utilizando Express v4.

// server.js
var express = require('express');  
var bodyParser = require('body-parser');  
var mongoose = require('mongoose');  
var cors = require('cors');  
var authCtrl = require('./auth');  
var middleware = require('./middleware');

// Configuramos Express
var app = express();  
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({extended: true}));  
app.use(cors());  
app.set('port', 3000);

// Importamos nuestros modelos, 
// en este ejemplo nuestro modelo de usuario
require('./models/user');

// Iniciamos las rutas de nuestro servidor/API
var router = express.Router();

// Rutas de autenticación y login
router.post('/auth/signup', auth.emailSignup);  
router.post('/auth/login', auth.emailLogin);

// Ruta solo accesible si estás autenticado
router.get('/private',middleware.ensureAuthenticated, function(req, res) {...} );

// Iniciamos el servidor y la base de datos
mongoose.connect('mongodb://localhost', function(err) {  
    // Comprobar errores siempre
    app.listen(app.get('port'), function(){
        console.log('Express corriendo en http://localhost:3000');
    });
});

Simplemente hemos importado los módulos necesarios y la configuración básica de Express. También he importado un archivo con el Schema del modelo User donde almacenaremos nuestros usuarios. Las rutas que utilizaremos serán /auth/signup para el registro con email y contraseña y /auth/login para autenticarnos.

Luego tendremos una ruta adicional, /private que sólo podremos acceder a ella si estamos logueados. Si nos fijamos, he creado un middleware para esta última ruta, que se ejecutará antes de la función controladora. Lo he separado en un módulo aparte, de esta manera podemos reutilizar esta función en todas las rutas que queramos que sean privadas.

De igual manera, en las funciones controladores de /auth/signup y /auth/login utilizo otras funciones importadas como son auth.emailSignup y auth.emailLogin que definiremos a continuación.

Controladores

En el fichero auth.js voy a definir las dos funciones controladoras para el registro y autenticación de usuarios.

// auth.js
var mongoose = require('mongoose');  
var User = mongoose.model('User');  
var service = require('./service');

exports.emailSignup = function(req, res) {  
    var user = new User({
        // Creamos el usuario con los campos
        // que definamos en el Schema
        // nombre, email, etc...
    });

    user.save(function(err){
        return res
            .status(200)
            .send({token: service.createToken(user)});
    });
};

exports.emailLogin = function(req, res) {  
    User.findOne({email: req.body.email.toLowerCase()}, function(err, user) {
        // Comprobar si hay errores
        // Si el usuario existe o no
        // Y si la contraseña es correcta
        return res
            .status(200)
            .send({token: service.createToken(user)});
    });
};

En emailSignup creo un nuevo usuario, con los campos que estimemos necesarios para nuestra aplicación, por ejemplo el email, nombre, contraseña, etc... Despues de salvar el usuario, enviamos un código 200 de OK en la respuesta, junto con un mensaje en el que pasaremos el token que creamos en la función service.createToken() que veremos a continuación.

Para el emailLogin, buscamos primero si el usuario existe y comprobamos que la contraseña es correcta o no. Si todo es OK, volvemos a enviar un código 200 en la respuesta HTTP junto con el token.

Codificando el JSON Web Token

Ahora vamos al "meollo" de este artículo, la creación de un Token que identifique a nuestro usuario en cada petición HTTP que realice.

Para codificar el token utilizamos una clave secreta. Es importante que esta clave permanezca lo más oculta posible. Una opción es almacenarla en un fichero config.js y ese fichero no subirlo al repositorio con .gitignore o la opción mejor es utilizar una variable de entorno (con process.env) que esté en nuestro servidor, y otra para nuestro entorno de desarrollo.

Sería algo así:

// config.js
module.exports = {  
  TOKEN_SECRET: process.env.TOKEN_SECRET || "tokenultrasecreto"
};

Cuando importemos el fichero config.js en la variable TOKEN_SECRET tendremos nuestra clave para codificar.

Creamos el servicio que utilizaremos para codificar el token. Para ello vamos utilizar la librería jwt-simple que nos facilita la vida a la hora de codificar el payload y hace todo el trabajo que expliqué en el post anterior.

// services.js
var jwt = require('jwt-simple');  
var moment = require('moment');  
var config = require('./config');

exports.createToken = function(user) {  
  var payload = {
    sub: user._id,
    iat: moment().unix(),
    exp: moment().add(14, "days").unix(),
  };
  return jwt.encode(payload, config.TOKEN_SECRET);
};

Creamos un objeto payload en el que ponemos tres atributos: sub, iat y exp. Que ya explicamos anteriormente. En sub almacenamos el ID del usuario que pasamos por parámetro.

También usamos la librería moment para ayudarnos en el manejo de fechas. Con moment().unix() conseguimos el tiempo actual en formato UNIX, y con moment().add(14, "days").unix() le estamos añadiendo 14 días al momento actual. Muy útil para establecer una fecha de creación y expiración.

Por úlitmo devolvemos el JSON Web Token, codificando el payload con nuestra clave secreta.

Acesso a rutas con autenticación.

Cada vez que accedamos a una ruta privada, sólo accesible si estamos autenticados, como por ejemplo /private, le pasamos el middleware ensureAuthenticated que a continuación programaremos:

// middleware.js
var jwt = require('jwt-simple');  
var moment = require('moment');  
var config = require('./config');

exports.ensureAuthenticated = function(req, res, next) {  
  if(!req.headers.authorization) {
    return res
      .status(403)
      .send({message: "Tu petición no tiene cabecera de autorización"});
  }

  var token = req.headers.authorization.split(" ")[1];
  var payload = jwt.decode(token, config.TOKEN_SECRET);

  if(payload.exp <= moment().unix()) {
     return res
         .status(401)
        .send({message: "El token ha expirado"});
  }

  req.user = payload.sub;
  next();
}

Lo primero que hacemos en la función es comprobar que la petición, req lleva la cabecera de autorización req.headers.authorization. Ésto lo envía el Frontend y lo veremos en un próximo post, con Angular.js

Si la petición no envía una autorización, envíamos el código de error 403 de acesso denegado. y si no, tomamos el token.

la cabecera, tendrá una pinta parecida a ésta:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbsciOiJIUzI1NiJ9.eyJzdWIiOiIWeRtU2ZWMyYjUyNjgxNzE2YmXiNzAxMzIiLCJpYXQiOjE0Mj10MjA0OTEsImV4cCI6MTQy67YzMDA5MX0.IH7ek7Rp_WQJvXeOd8zrBIpeFi4W6kUi_6htmaxv7Ow  

Sólo tenemos que obtener el token de ese String y lo hacemos con el método split de JavaScript:

var token = req.headers.authorization.split(" ")[1];  

Decodificamos ese token con la función decode y la clave secreta y ya podemos identificar al usuario, con el atributo sub del objeto payload, que según este ejemplo serán un ObjectID de Mongo.

En la próxima entrada, veremos como programar la autenticación en la parte del cliente con Angular.js.

Autenticación con Token en AngularJS

$
0
0

Bienvenid@ a la última entrega de la serie de Autenticación basada en token en aplicaciones web. En las anteriores entradas vimos las bases de este método y cómo programarlo en nuestro servidor o API REST con Node.js. En éste artículo veremos como implementarlo en el lado del cliente con Angular.js

Usando librerías de terceros

Podemos hacerlo de varias maneras. Implementarlo manualmente o utilizar una librería que nos facilite el desarrollo. Yo recomiendo esto último y en concreto la librería Satellizer, desarrollada por Sahat Yalkabov que desarrolló durante su etapa de non-student en la Hacker School de Nueva York.

Esta librería soporta autenticación por usuario/contraseña además de proveedores OAuth como Facebook, Twitter, Google, Github, etc... Es sencilla de usar y funciona perfectamente. A continuación veremos como configurarla.

Instalación y configuración

Primero necesitamos instalarla, podemos hacerlo por Bower o si usamos Browserify por NPM.

$ bower install --save satellizer

De seguido, en nuestro fichero principal de Angular, supongamos el app.js, importamos el módulo y configuramos la librería. El nombre de la directiva que utiliza Satellizer es $auth y $authProvider.

angular  
    .module("myApp", ["satellizer"])
    .config(function($authProvider) {
        // Parametros de configuración
        $authProvider.loginUrl = "http://api.com/auth/login";
        $authProvider.signupUrl = "http://api.com/auth/signup";
        $authProvider.tokenName = "token";
        $authProvider.tokenPrefix = "myApp",
    });

En $authProvider.loginUrl y $authProvider.signupUrl indicamos cual es la ruta de nuestro servidor o API REST que maneja la autenticación. Como vimos en el anterior post, éstas rutas on /auth/login y /auth/signup.

En $authProvider.tokenName le indicamos un nombre al token y $authProvider.tokenPrefix para añadirle un prefijo al nombre del token por si queremos diferenciarlo en nuestro LocalStorage de otros. En este caso, el token quedará guardado en LocalStorage con la clave myApp_token.

Controladores

Lo siguiente a implementar son los controladores. Tendremos dos principalmente, el de login y el de registro, además del de logout.

angular  
    .module("myApp.controllers")
    .controller("SignUpController", SignUpController)
    .controller("LoginController", LoginController);
    .controller("LogoutController", LogoutController);

function SignUpController($auth, $location) {  
    var vm = this;
    this.signup = function() {
        $auth.signup({
            email: vm.email,
            password: vm.password
        })
        .then(function() {
            // Si se ha registrado correctamente,
            // Podemos redirigirle a otra parte
            $location.path("/private");
        })
        .catch(function(response) {
            // Si ha habido errores, llegaremos a esta función
        });
    }
}

function LoginController($auth, $location) {  
    var vm = this;
    this.login = function(){
        $auth.login({
            email: vm.email,
            password: vm.password
        })
        .then(function(){
            // Si se ha logueado correctamente, lo tratamos aquí.
            // Podemos también redirigirle a una ruta
            $location.path("/private")
        })
        .catch(function(response){
            // Si ha habido errores llegamos a esta parte
        });
    }
}

function LogoutController($auth, $location) {  
    $auth.logout()
        .then(function() {
            // Desconectamos al usuario y lo redirijimos
            $location.path("/")
        });
}

Es un código sencillo si ya has visto AngularJS anteriormente. Creamos las funciones correspondientes que utilizaremos desde las vistas this.signup, this.login. Estas funciones a su vez llamarán a la librería Satellizer a través de la directiva $auth llamando a las funciones $auth.login(), $auth.signup() y $auth.logout().

Estas funciones por debajo, realizan todo el manejo de insertar en la cabecera HTTP el token de autenticación que recibe del servidor cuando se registra/autentica y que envía en cada petición HTTP una vez autenticado.

¿Dónde se almacena el Token?

Vamos a ver un poco como está hecho Satellizer por dentro. Puedes mirarlo en su repositorio en GitHub ya que es OpenSource, e incluso puedes ayudar a mejorarlo con tus aportes :)

Entre todos los módulos que están programados en Satellizer, vemos uno llamado satellizer.shared donde se comparten los métodos y funciones que utiliza el resto de la librería. Digamos que éste es el núcleo de la funcionalidad.

shared.getToken() busca en nuestro LocalStorage la clave que hemos definido para almacenar nuestro Token y nos lo devuelve

shared.getToken = function() {  
          var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;
          return $window.localStorage[tokenName];
        };

shared.getPayload() toman el token y devuelve el payload que es la 2a parte del token

shared.getPayload = function() {  
          var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;
          var token = $window.localStorage[tokenName];

          if (token && token.split('.').length === 3) {
            var base64Url = token.split('.')[1];
            var base64 = base64Url.replace('-', '+').replace('_', '/');
            return JSON.parse($window.atob(base64));
          }
        };

Y por último la función shared.setToken(), almacena el token recibido en el LocalStorage:

shared.setToken = function(response, isLinking) {  
          var token = (response.access_token) || (config.tokenRoot && response.data[config.tokenRoot] ?
            response.data[config.tokenRoot][config.tokenName] : response.data[config.tokenName]);
          var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;

          if (!token) {
            tokenName = config.tokenRoot ? config.tokenRoot + '.' + config.tokenName : config.tokenName
            throw new Error('Expecting a token named "' + tokenName + '" but instead got: ' + JSON.stringify(response.data));
          }

          $window.localStorage[tokenName] = token;

          if (config.loginRedirect && !isLinking) {
            $location.path(config.loginRedirect);
          }
        };
¿Cómo se envía el token en cada petición HTTP?

De eso se encarga la directiva $httpProvider que funciona como interceptor o middleware y se activa en cada petición HTTP.

//...
.config(['$httpProvider', 'satellizer.config', function($httpProvider, config) {
      $httpProvider.interceptors.push(['$q', function($q) {
        var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;
        return {
          request: function(httpConfig) {
            var token = localStorage.getItem(tokenName);
            if (token && config.httpInterceptor) {
              token = config.authHeader === 'Authorization' ? 'Bearer ' + token : token;
              httpConfig.headers[config.authHeader] = token;
            }
            return httpConfig;
          },
          responseError: function(response) {
            return $q.reject(response);
          }
        };
      }]);
    }]);

De esta manera, en cada petición HTTP, se inserta en las cabeceras el token si lo tenemos en el LocalStorage y ya despues el backend (nuestro servidor o API) se encarga de ver si existe, es correcto o no y devolver el código de respuesta para cada caso.

Rutas y vistas

Volvemos al módulo principal de nuestra aplicación y añadimos las rutas del frontend a continuación de la configuración del $authProvider podemos usar ngRoute o ui.route si queremos tener estados en lugar de rutas y poder tener vistas anidadas (nested views). Yo suelo utilizar ui.router me parece más cómodo. Para ello primero instalamos la librería correspondiente:

$ bower install --save angular-ui-router

Y lo configuramos en app.js

angular  
    .module("myApp", ["satellizer", "ui.router"])
    .config(function($authProvider, $stateProvider) {
        // Parametros de configuración
        $authProvider.loginUrl = "http://api.com/auth/login";
        $authProvider.signupUrl = "http://api.com/auth/signup";
        $authProvider.tokenName = "token";
        $authProvider.tokenPrefix = "myApp",

        // Configuración de las rutas/estados
        $stateProvider
            .state("home", {
                url: "/",
                templateUrl: "views/index.html"
                controller: "HomeController"
            })
            .state("login", {
                url: "/login",
                templateUrl: "views/login.html",
                controller: "LoginController",
                controllerAs: "login"
            })
            .state("signup", {
                url: "/signup",
                templateUrl: "views/signup.html",
                controller: "SignUpController",
                controllerAs: "signup"
            })
            .state("logout", {
                url: "/logout",
                templateUrl: null,
                controller: "LogoutController"
            })
            .state("private", {
                url: "/private",
                templateUrl: "views/private.html",
                controller: "PrivateController",
                controllerAs: "private"
            });
    });

En este código he configurado dos rutas adicionales, la de Home en / y la de Private en /private pero éstas no las voy a desarrollar en este ejemplo. Esas ya son propias de tu aplicación.

Lo que si voy a mostrar es como serían las vistas para el login y el signup.

<!-- views/signup.html -->  
<form ng-submit="signup.signup()" method="post">  
    <input type="email" ng-model="signup.email"/>
    <input type="password" ng-model="signup.password"/>
    <button type="submit">Registrarse</button>
</form>  
<!-- views/login.html -->  
<form ng-submit="login.login()" method="post">  
    <input type="email" ng-model="login.email"/>
    <input type="password" ng-model="login.password"/>
    <button type="submit">Autenticarse</button>
</form>  

En ellas vemos los ng-model que utilizamos y que obtenemos en el controlador.

Si quieres más información (en inglés) sobre estos temas de autenticación por Token, te dejo unos enlaces a blogs y websites que me han servido para documentarme y aprender a manejar este sistema.

Fuentes

Cómo servir tu API REST en Node.js a través de Nginx

$
0
0

Si seguimos los pasos del desarrollo web moderno, separando nuestro Frontend de nuestro Backend, realizando autenticación basada en token, utilizando un API RESTFul que sirva JSON, etc... llega un momento en que tenemos que servir nuestro API desde nuestro dominio. ¿Cómo podemos hacerlo?

Una opción es usar Nginx, no solo como servidor web o balanceador de carga, si no también como Proxy inverso para redirigir las peticiones según la URL.

Imaginemos que nuestra aplicación frontend está almacenada en el directorio de nuestro servidor /var/www/ y que tenemos nuestra API en Node.js corriendo en localhost:3000

Ahora lo que queremos que la parte cliente y todas las rutas del frontend (que pueden ser servidas con AngularJS) se sirvan a través de la ruta /. Y que nuestra API en Node.js se sirva a través de la ruta /api, en plan que si escribimos http://midominio.com/ sirva el frontend y http://midominio.com/api sirva el API y podamos hacer las peticiones AJAX a esa URL.

Esto lo conseguimos con el siguiente fichero de configuración de Nginx:

# HTTP proxy
server {  
    listen 80;
    server_name midominio.com;

    access_log /var/log/nginx/nginx.access.log;
    error_log /var/log/nginx/nginx.error.log;

    client_max_body_size 5M;

    location / {
        add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";

        # Ruta de los ficheros estáticos
        root /var/www;
        try_files $uri $uri/ /index.html =404;
    }

    location /api {
        proxy_set_header 'Access-Control-Allow-Origin' 'http://midominio.com';
        proxy_set_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
        proxy_set_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin';

        proxy_pass http://127.0.0.1:3000;
        proxy_redirect off;
        proxy_buffering on;

        proxy_set_header    Host        $host;
        proxy_set_header    X-Real-IP   $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    origin      'http://midominio.com';
    }
}

Es importante, además de indicar para cada URL, que ruta tomar, los siguientes campos:

try_files $uri $uri/ /index.html =404;  

Esto nos permite que el HTML5Pushstate que en ocasiones usamos en AngularJS, nos funcione. De otra manera es posible que tengamos fallos y errores cuando sirvamos las vistas del Frontend en Angular.js

proxy_set_header 'Access-Control-Allow-Origin' 'http://midominio.com';  
proxy_set_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';  
proxy_set_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin';  

Esto habilita CORS para nuestro API. Aunque lo tengamos habilitado en nuestra configuración de Express dentro de Node, es conveniente configurarlo en NGINX, ya que es la primera barrera que pasan nuestras peticiones HTTP y así no entramos en conflicto

proxy_redirect off;  
proxy_buffering on;  
proxy_set_header    origin  'http://midominio.com';  

También es importante declarar estos campos, ya que si no nuestro API puede no funcionar correctamente, con redirect a off y buffering a on nos evitamos sustos.

Por último indicar la cabecera origin con la URL de nuestro dominio, para que el Cross-Origin no se vea afectado.

El escritorio de un desarrollador web

$
0
0

Si eres desarrollador web, habrás notado que muchas veces, si trabajas con un ordenador portátil, te falta pantalla para colocar todas las ventanas que tienes abiertas, o tu espalda se resiente tras horas de trabajo encorvado mirando tus 13 o 15 pulgadas.

En este post, he querido recopilar los accesorios que he ido adquiriendo en los últimos meses (y algunos que ya tenía) que me ayudan en mi día a día como desarrollador web.

Escritorio de un desarrollador web

  1. Laptop
  2. Monitor Externo
  3. Auriculares
  4. Tablet Monitor
  5. Elevador de portátil
  6. Teclado Bluetooth
  7. Disco duro portátil
  8. Chromecast
  9. Altavoces Domésticos
  10. Mesa
  11. Silla

Laptop

Mi herramienta principal de trabajo es un MacBook Pro Retina de 13", la edición Late 2013, que compré durante nuestra visita a Estados Unidos. Comprado en una Apple Store de San Francisco. Más hipster no se puede ser :P

macbookpro

Apple MacBookPro Retina 13" - Late 2013

Ya han salido varias revisiones de este laptop, la mía en concreto tiene las siguientes características

  • Sistema: Mac OS X Yosemite v10.10.2
  • Procesador: Intel Core i5 2,4GHz
  • Memoria: 4GB 1600 MHz DDR3
  • T.Gráfica: Intel Iris 1536 MB
  • Almacenamiento: 128 GB SSD

Además tiene 2 conectores USB, 2 conectores Thunderbolt 2, Salida para auriculares, Salida HDMI y Slot para leer tarjetas SD de memoria.

Y lo que más me gusta es la batería, con un uso intensivo, al cabo de año y medio tengo unas 5 horas de batería. Si le quito el WiFi puedo llegar a 7. Los modelos actuales han mejorado aún más.

El modelo actual supera éstas características. Para mi actualmente son más que suficientes, por tanto si estás pensando en adquirir un MacBook Retina, ve a por él.

Monitor Externo

Estuve un tiempo buscando un bueno monitor para utilizar como monitor externo, que no fuera muy caro, que se viera bien y a ser posible HDMI. Es una misión complicada, pero dí con uno que además estéticamente es bonito y no fue un desembolso de dinero atroz.

Monitor Samsung 24 HDMI

Samsung LS24D391HL, LED, 24", HDMI

Se trata del monitor Samsung LS24D391HL de 24", LED, con entradas tanto VGA como HDMI. Su precio en Amazon, donde lo compré es de unos 160€ y se ve realmente bien. No es un Apple Cinema Display, pero no tiene nada que envidiarle ;).

Si buscas un buen monitor para tu Laptop y HDMI, es una muy buena opción.

Auriculares

Cuando necesito concentrarme, estos auriculares me vienen de perlas. No tienen cancelación de ruido, ni son bluetooth, pero por el precio que tienen (26€) son bastante buenos, ya que si estás escuchando música o algún video, solo escucharás eso.

sennheiser

Sennheiser HD 202 II

Si buscas unos buenos audífonos de diadema y no quieres dejarte un pastizar, te los recomiendo y también los vende Amazon.

Tablet Monitor

Tengo un iPad3 desde hace ya unos años, lo uso bastante para leer blogs a través de Flipboard, y libros técnicos en PDF, ya que en ese sentido me resultan más cómodos de leer que en un Kindle.

DuetDisplay

Recientemente han lanzado una aplicación para iOS y Mac, desarrollada por ex-ingenieros de Apple, que permite utilizar tu iPad como monitor externo, sin nada de lags extraños. Se llama Duet Display, cuesta 14€ pero merece la pena si quieres tener un monitor externo portatil, o un segundo monitor externo como tengo yo, para tener tu terminal o slack abiertos y separados del workspace.

Elevador de portátil

Como decía al principio del post, trabajar en una mesa con un portatil muchas horas hace que nuestra espalda se fuerce en una mala postura. La pantalla debe estar a la altura de nuestros ojos, y en los portátiles eso es complicado.

Por suerte, existen elevadores de portatiles para esto. Hay de todo, más caros que el portátil en si o más económico.

elevador de portatil

Ah Stands SLT001E

Yo tengo el de la imagen que adquirí hace unos días en Amazon, por 25€ regulable a 5 alturas, y si tienes que transportarlo, desmontándolo ocupa muy poco.

Teclado Bluetooth

Al tener el portátil elevado, se hace necesario un teclado adicional. Los de Apple son muy caros, yo quería uno similar pero no quería dejarme otra pasta en eso.

Teclado Bluetooth

Encontré éste en Amazon, por 20€, que si bien no tiene la misma calidad que uno de Apple, cumple su trabajo. Sirve también para tablets. Si buscas uno barato, pero que funcione te lo recomiendo.

Disco Duro Portátil

El Mac viene con 128GB de SSD. Para programas y archivos frecuentes es un buen tamaño, pero si tienes que almacenar fotos, archivos de gran tamaño, vídeos, etc.. se te queda corto.

Para ello tengo un disco duro portátil externo de 2TB, donde aparte de esos archivos voluminosos, guardo los backups del Mac que se realizan con TimeMachine. No ocupa mucho y es fácil de transportar. Tampoco es demasiado caro, ya que es un almacenamiento estándar, si fuera SSD sería mucho más costoso, pero no merece la pena a menos que edites muchos videos o manejes de manera frecuente archivos muy pesados.

WD-MyPassport

WD MyPassport 2TB

Mi disco en cuestión es un Western Digital, modelo MyPassport y lo puedes adquirir en Amazon por menos de 100€. Su conexión es USB 3.0 y no he tenido pegas por ahora y llevo bastante tiempo usándolo (+3 años)

Chromecast

Me lo regaló Paola el año pasado por mi cumpleaños y lo usamos bastante. No solo como reproductor de peliculas sin necesidad de cables, si no también para ver videotutoriales o conferencias en la TV del Salón, mientras seguimos utilizando el ordenador para otras cosas.

También puedes usarlo desde el móvil, por lo que su usabilidad es ilimitada, tan solo lo que puedas ver en tu navegador, lo puedes ver en la TV.

Chromecast

Google Chromecast

Te olvidas de cables y estar instalando DLNAServers. Sólo cuesta 35€ y se instala en un momento.

Altavoces Domésticos

Por último, en la foto de mi escritorio, aparecen unos altavoces bluetooth. No son imprescindibles para desarrollar, pero si quieres escuchar música con mejor calidad que el altavoz del portátil, son una buena opción.

Al ser bluetooth, puedes ponerlos en cualquier sitio de la casa y reproducir música de Spotify desde tu ordenador.

Son antiguos, ya en Amazon no los venden, pero dejo por aquí el modelo si a alguien le interesa.

Philips AS141/12

Philips AS141/12

Bonus Extra

Mesa

Para la mesa no hay que dejarse mucho dinero, simplemente un tablero de IKEA con 4 patas cumple a la perfección, a menos que quieras un standing desk.

El tablero que compartimos Paola y yo es éste de IKEA que sale por 42,50€

Tablero

LINNMON

Silla

Para la silla de oficina si conviene invertir algo más de dinero, al fin y al cabo pasamos muchas horas en ella y es importante que estemos cómodos y nuestra espalda no sufra.

Hay de todo, desde muy caras a medianamente costosas... Yo no me puedo dar el lujo en este momento de comprar una muy cara, así que opté por IKEA de nuevo y actualmente uso ésta que me costó 70€ y por lo menos la espalda no me duele al final del día, lo cual es mucho :D

silla

VILGOT


Y básicamente eso es todo lo que hay en mi mesa, aparte de la taza de café reglamentaria :D.

Y tú, ¿Qué otros dispositivos o accesorios utilizas en tu escritorio?

Viewing all 164 articles
Browse latest View live