Bonjour à tous !

Mardi 29 Juillet a eu lieu le premier DCube Lab dédié aux technologies liées au langage Javascript. Nous avons entamé cette série avec Sails.js, un stack MVC pour Node. Etant donné que c’est les vacances et que tout le monde n’a pas pu assister à ce Lab je vous propose un step by step de tout ce que l’on a fait ce soir-là.

Node ne vous intéresse peut-être pas mais je vous encourage à suivre ce billet si vous souhaitez participer aux prochains Labs car Sails.js sera à nouveau utilisé pour résoudre certaines problématiques.

Avant de commencer il vous faut un éditeur de texte.

Voici une liste parmi ceux que nous avons utilisés :

Pour ceux qui comme moi vouent un culte aux outils JetBrains vous pouvez opter pour Webstorm, un IDE Javascript particulièrement puissant.

Il vous faut aussi installer Node.js et MongoDB. Les deux technos vous seront utiles pour les prochains Labs !

Lors de la conférence du 26 mars à Sup’Info, j’avais déjà abordé Sails.js, pour les absents je vous laisse consulter la présentation sur slideshare (cela vous donnera une bonne vision sur la techno ;-p).

 

Installation et manipulation de la CLI

Une fois votre environnement de développement en place ouvrez un terminal et tapez :

npm install sails -g

Pour ceux qui débute en Node, NPM est le module de gestion des packages. Cette commande va vous permettre d'installer Sails.js dans les packages globaux de Node et donc de pouvoir y accéder partout. Sails contient aussi une CLI (command line interface). Grâce à celle-ci vous disposez de commandes d'assistance au développement. Pour commencer, placez vous dans le répertoire où vous voulez stocker votre projet et tapez la commande :

sails new MyExemple

La CLI Sails va via cette commande vous générer la structure de votre application dans le répertoire MyExemple. Vous devez à présent avoir ceci dans le répertoire :

sailsnew

Pour lancer l’application web il vous suffit à présent d’utiliser la commande lift :

sails lift

 Sails se met en écoute sur le port 1337 (Si vous vous demandez pourquoi consultez cet article : http://fr.wikipedia.org/wiki/Leet_speak).

lifts

Sur le path : http://localhost:1337 vous devriez obtenir la page par défaut de Sails :

sails-home

La prochaine commande de la CLI que nous allons utiliser vous permet de générer du code de base :

sails generate Todo

generate permet comme son nom l’indique de générer la structure d’un objet de type model. Vous devriez retrouver le fichier Todo.js dans le répertoire api/model. Nous allons à présent éditer ce fichier pour lui définir des propriétés.

 

Model & automatic Rest backend

La définition de modèle dans Sails fonctionne via les validations de schémas. La structure des objets est donc définit par un ensemble d’attributs sur lesquels il est possible de préciser le type mais aussi les validations. Pour le besoin de notre premier objet nous allons définir deux attributs, un titre et un statut (qui déterminera si le Todo a été fait ou pas). Le titre sera de type string, en plus d’être unique et obligatoire. Le statut sera de type boolean et aura par défaut une valeur à false.

Voici le code qui permet de donner les différents aspects à l'objet :

module.exports = {
    attributes : {
        title : {
            type : 'string',
            required : true,
            unique : true
        },
        done : {
            type : 'boolean',
            defaultsTo : false
        }
    }
};

Sans vous en rendre compte vous venez de faire 90% du travail. Sails va à présent pouvoir utiliser cette définition et automatiser un certains nombres d'opérations.

Pour commencer, relancez l'application à l'aide de la commande lift et attaquez le path http://localhost:1337/Todo.

Vous devriez avoir en réponse un Json vide.

Le serivce Rest automatisé par Sails répond donc correctement mais pour le tester en profondeur il nous faut des données. Pour cela munissez vous d'un client Rest. Si vous utilisez Webstorm vous en avez un dans l'onglet Tools sinon il est possible d'utiliser sous chrome le plugin PostMan.

Utilisez une requête en méthode HTTP POST dont le Content-Type est data/json, le path est http://localhost:1337/Todo et le corps contient le Json suivant :

{ "title" : "Exemple", "done" : true }

En retour le service Rest devrait vous confirmer la bonne insertion des données en vous renvoyant le Json correspondant à l'objet Todo persisté :

{
    "title" : "Exemple",
    "done" : true,
    "createdAt" : "2014-08-05T12:05:55.458Z",
    "updatedAt" : "2014-08-05T12:05:55.458Z",
    "id" : 1
}

En plus des propriétés définies, Sails enrichit les entités avec deux dates (création et modification) et un Identifiant incrémenté.

Afin de vérifier que les validations fonctionnent, tentez de refaire la même requête POST. Vous devriez obtenir une erreur sur la propriété title vu qu’elle est déclarée unique. Idem si vous ne définissez pas de propriété title dans votre corps de requête l’erreur liée au required sera levée. Enfin si la propriété done n’est pas saisie elle sera par défaut à false.

Une fois que vous aurez rajouté plusieurs données il est possible de les filtrer via des requêtes de type GET en précisant en paramètres les noms des propriétés sur lesquels filtrer. Voici quelques exemples :

http://localhost :1337/Todo?title=Exemple

http://localhost:1337/Todo?done=false

Je vous laisse explorer de vous-même les capacités de suppression et de mise à jour via les méthodes HTTP DELETE et PUT, elles doivent fonctionner parfaitement !

Comme vous avez pu le constater dans cette partie, Sails.js gère tout la partie Rest out of the box. Code less do more !

 

MVC et ORM

Bien que Sails.js gère de manière très puissante le montage de service Restfull, la technologie est avant tout un Stack MVC basé sur Express. Dans la première partie vous aviez utilisé la commande :

sails generate Todo

En plus du fichier Todo.js crée dans le répertoire api/model, Sails a aussi généré la structure d'un contrôleur. Le fichier est présent dans api/controllers et porte le nom de TodoController.js.

Pour définir une action dans le controller il suffit de rajouter une fonction qui accepte deux paramètres en entrée : un objet requête et un de réponse. pour faire un exemple nous allons créer une action qui va nous renvoyer la liste des todos qui ne sont pas finalisés. Voici la structure du contrôleur avec l'action (nommée getAll) :

module.exports = {
    _config : {},

    getAll : function(req, res){

    }
};

Ensuite, il faut une vue à laquelle binder les données. A la racine du projet, dans le répertorie views, rajoutez un répertoire todo qui contiendra les vues renvoyées par le contrôleur todo. Ensuite ajoutez un fichier getAll.ejs contenant le code suivant :

<% for(var i = 0; i < todos.length; i++){ %>
<p>
    <%= todos[i].title %>
    <%= todos[i].done %>
</p>
<% } %>

Sur cette vue le contrôleur va bindé un objet contenant la propriété "todos" qui correspondra à la collection des Todos à finaliser. pour chaque élément le titre et le statut seront affichés.

Côté contrôleur pour récupérer les données il faut utiliser l'ORM Waterline embarqué dans Sails. Encore une fois le stack va faire tout le travail car en définissant le modèle Todo dans la partie 2, le contrôleur peut directement accéder aux données et faire des opérations de recherche. Dans l'action getAll, rajoutez une recherche sur les todos dont la propriété done est à false :

Todo.find().where({ done : false }).exec(function(err, data){

});

Il ne reste plus qu'à renvoyer la vue bindée aux données contenues dans le paramètre data :

res.render('todo/getAll', { todos : data });

Au final vous devriez avoir ce code dans le contrôleur :

module.exports = {
    _config : {},
    getAll : function(req, res){
        Todo.find().where({ done : false }).exec(function(err, data){
            res.render('todo/getAll', { todos : data });
        });
    }
}

Si vous attaquez la route http://localhost/todo/gelAll vous devriez voir le rendue de l’action.

Il est possible de configurer les paths des actions afin de coller au mieux aux besoins. Dans notre exemple pourquoi ne pas exécuter l’action getAll sur la route http://localhost/todos ? Pour faire cette opération il existe dans le projet un répertoire config qui se trouve à la racine. A l’intérieur on trouve le fichier de configuration des routes : routes.js. Par défaut seul la route principale est définit. Elle pointe sur une vue contenant du code statique (la fameuse page par défaut de sails). :

module.exports.routes = {
    '/' : {
        view : 'home/index'
    }
};

A la suite de la définition du path d’entrée rajoutez celui que vous voulez définir en y associant un contrôleurs et une action :

'todos' : {
    controller : 'todo',
    action : 'getAll'
}

Il est aussi possible de spécifier une méthode HTTP :

'post /todos' : {
    controller : 'todo',
    action : 'getAll'
}

Ici l’appel ne fonctionnera donc qu'avec la méthode POST. Si vous l’appeler depuis votre client Rest vous devriez obtenir le résultat de l’action.

Nota : Au cours du lab les participants ont trouvé ce point déconcertant. Il est vrai qu’actuellement la définition des méthodes n’est pas élégante dans Sails, les développeurs auraient plutôt du définir une propriété ‘type’ ou ‘method’ afin que cela soit plus clair.

Vu que nous sommes en pleine modification de la configuration c’est le moment de répondre à une question que vous vous êtes peut-être posée : où sont stockées les données ?

L’ORM Waterline utilise des adapters qui permettent de prendre en charge la persistance via de multiple source (Sql, NoSql ou autre). La configuration de ces adapters se trouve dans le fichier adapters.js. Si vous ouvrez ce fichier vous devriez avoir un adapter par défaut, sails-disk :

module.exports.adapters = {
    'default' : 'disk',

    disk : {
        module : 'sails-disk'
    }
}

Il est possible d’en définir d’autres, comme celui qui permet d'utiliser MongoDB pour la persistance :

mongo : {
    module : 'sails-mongo',
    host : 'localhost',
    port : 27017,
    database : 'todo'
}

Pour le rendre actif il suffit de remplace la valeur de la propriété default par le nom de notre adapter mongo :

'default' : 'mongo'

Etant donné que la configuration de cette adapters demande le module sails-mongo il faut le rapatrier dans le projet via NPM. A la racine du projet dans votre terminal tapez :

npm install sails-mongo

A présent Waterline utilisera votre instance MongoDB pour la persistance. L’ORM peut prendre en charge Postgre, MySql, MongoDb, Redis et bien d’autres sources. D’ailleurs il est tout à fait possible de développer son propre adapter pour supporter un autre SGBD (comme par exemple SqlServer)

 

Conclusion

Dans ce premier lab nous avons découvert toute la puissance de Sails. C’est à l’heure actuelle un des seuls Stack RoR like (inspiré par Ruby on Rails). Personnellement j’adore cette techno car elle est simple et puissante. Quelques lignes de code suffisent pour déclencher un nombre de features assez impressionnantes ! C’est donc une technologie que je recommande fortement si vous vous intéressez au développement d’application Web en Node.js. Cependant étant donné que Sails surcouche une grosse partie de la mécanique du framework MVC Express, je vous conseil très fortement d’apprendre à l'utiliser avant.

  A bientôt pour le prochain Lab DCube !

Catégories : Javascript

DCube · 20 août 2014 à 21 h 32 min

[…] je l’ai déjà expliqué dans mon article sur Sails.js (à lire ici) l’argument -g de la commande permet d’installer Bower dans les packages globaux de […]

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *