Créer une application Todo List avec Node.js et Geddy

Dans ce didacticiel en trois parties, nous allons nous plonger dans la création d'une application de gestion de liste de tâches dans Node.js et Geddy. Ceci est la deuxième partie de la série, où nous allons créer une application de gestion de liste simple à faire.


résumer

Pour rappel, la dernière fois que nous avons installé Node et Geddy, généré une nouvelle application et appris à démarrer le serveur. Dans ce tutoriel, nous allons construire sur ce que nous avons fait la dernière fois, alors assurez-vous de l'avoir terminé avant de continuer..


Génération de la ressource Todo

Geddy a un générateur de ressources intégré; Cela nous permettra de générer automatiquement un modèle, un contrôleur, des vues et des itinéraires pour une ressource spécifique. Notre application de liste de tâches n'aura qu'une seule ressource: faire. Pour le générer, il suffit de CD dans le répertoire de votre application (cd path / to / your / todo_app) et courir:

ressource geddy todo

Vous devriez maintenant avoir ces fichiers ajoutés à votre application:

  • app / models / todo.js
  • app / controllers / todos.js
  • app / vues / todos /
    • index.html.ejs
    • show.html.ejs
    • edit.html.ejs
    • add.html.ejs

Votre config / router.js devrait également avoir cette annexe:

routeur.resource ('todos');

Qu'est-ce que tout cela fait

Si vous êtes nouveau sur MVC, tout cela peut vous paraître un peu décourageant. Ne vous inquiétez pas, c'est vraiment simple une fois que vous avez compris.

modèles / todo.js: Ce fichier est où nous définirons notre faire modèle. Nous allons définir un certain nombre de propriétés que tous faireont. Nous allons aussi écrire quelques validations de données ici.

contrôleurs / todos.js: Ce fichier est où tous les / todos / les itinéraires finissent. Chaque action dans ce contrôleur a un itinéraire correspondant:

GET / todos / => index POST / todos / => créer GET / todos /: id => show PUT / todos /: id => mettre à jour DELETE /: id => supprimer GET / todos /: id / add = > ajouter GET / todos /: id / edit => edit

vues / todos /: Chaque fichier ici correspond à l’un des fichiers OBTENIR itinéraires que nous vous avons montré ci-dessus. Ce sont les modèles que nous utilisons pour générer le front-end de l'application. Geddy utilise EJS (JavaScript incorporé) comme langage de modélisation. Cela devrait vous paraître familier si vous avez déjà utilisé PHP ou ERB. En gros, vous pouvez utiliser le code JavaScript que vous souhaitez dans vos modèles..

Se faire une idée des itinéraires

Maintenant que nous avons généré un tas de code, vérifions que nous avons tous les itinéraires dont nous avons besoin. Lancez l'application à nouveau (geddy) et pointez votre navigateur sur http: // localhost: 4000 / todos. Vous devriez voir quelque chose comme ça

Allez-y et essayez ça pour l'autre OBTENIR itinéraires aussi:

  • http: // localhost: 4000 / todos / quelque chose
  • http: // localhost: 4000 / todos / add
  • http: // localhost: 4000 / todos / quelquechose / edit

Tout bon? Bon, continuons.


Création du modèle Todo

Dans Geddy (et la plupart des autres frameworks MVC), vous utilisez des modèles pour définir le type de données avec lequel votre application fonctionnera. Nous venons de générer un modèle pour notre faires, voyons ce que cela nous a donné:

var Todo = function () // Un code mis en commentaire; // Encore du code commenté Todo = geddy.model.register ('Todo', Todo);

Les modèles sont assez simples dans Geddy. Nous venons de créer une nouvelle fonction constructeur pour notre faires et en l’enregistrant comme modèle dans geddy. Définissons quelques propriétés pour notre faires. Supprimez tout le code mis en commentaire et ajoutez-le à la fonction constructeur:

var Todo = function () this.defineProperties (titre: type: 'chaîne', obligatoire: vrai, id: type: 'chaîne', requis: vrai, statut: type: 'chaîne', requis : vrai ); ;

Notre faires aura un titre, un identifiant et un statut, et les trois seront nécessaires. Maintenant fixons quelques validations pour notre faires.

var Todo = function () this.defineProperties (titre: type: 'chaîne', obligatoire: vrai, id: type: 'chaîne', requis: vrai, statut: type: 'chaîne', requis : vrai ); this.validatesPresent ('title'); this.validatesLength ('title', min: 5); this.validatesWithFunction ('status', fonction (status) return status == 'open' || status == 'done';); ;

Nous validons que le titre est présent, qu'il a une longueur minimale de 5 caractères et nous utilisons une fonction pour valider que le statut est soit ouvrir ou terminé. Il existe de nombreuses fonctions de validation intégrées. Allez-y, jetez un œil au projet sur http://github.com/mde/geddy pour en savoir plus à leur sujet..


Création de l'adaptateur de modèle Todo

Maintenant que nous avons configuré notre modèle todo, nous pouvons créer un emplacement pour stocker nos modèles. Pour les besoins de ce didacticiel, nous allons simplement garder les données en mémoire. Nous accrocherons un tableau de todos à notre groupe geddy objet pour coller les données. Dans la prochaine partie de cette série, nous allons commencer à obtenir ces données persistantes dans une base de données.

Modification de votre fichier init.js

Ouvrez votre config / init.js fichier. Tout ce qui devrait y figurer maintenant est un gestionnaire d'exception non capturé:

// Ajouter un gestionnaire d'exception non capturée dans des environnements de type prod si (geddy.config.environment! = 'Development') process.addListener ('uncaughtException', function (err) geddy.log.error (JSON.stringify (err ));); 

Juste après ce bloc de code, accrochons notre tableau du geddy global:

geddy.todos = [];

Là, maintenant nous avons un endroit pour stocker notre faires. Rappelez-vous que ceci est dans la mémoire de votre application, donc il disparaîtra au redémarrage du serveur..

Création de l'adaptateur de modèle

Un modèle-adaptateur fournit la base enregistrer, retirer, charge, et tout méthodes dont un modèle a besoin. Notre source de données est assez simple (juste un tableau!), L'écriture de notre adaptateur de modèle doit donc l'être aussi.

Créer un répertoire dans lib appelé model_adapters et créer un fichier dans lib / model_adapters appelé todo.js. Ouvrons ce fichier et ajoutons du code standard:

var Todo = new (function () ) (); exports.Todo = Todo;

Tout ce que nous faisons ici est de configurer un nouvel objet vierge à exporter vers tout ce qui finit par nécessiter ce fichier. Si vous souhaitez en savoir un peu plus sur le fonctionnement de la méthode require de Node, cet article présente un assez bon aperçu. Dans ce cas, notre init.js le fichier fera le nécessaire.

Nécessite l'adaptateur de modèle dans init.js

Nous avons donc créé un nouvel objet adaptateur de modèle Todo. C'est assez stérile pour le moment, mais nous y reviendrons bientôt. Pour le moment, nous devrons revenir à init.js et ajouter du code pour qu'il soit chargé dans notre application au démarrage. Après le geddy.todos = []; dans config / init.js ajoutez ces deux lignes:

geddy.model.adapter = ; geddy.model.adapter.Todo = require (process.cwd () + '/lib/model_adapters/todo').Todo;

Nous avons créé un objet adaptateur de modèle vierge et y avons ajouté l'adaptateur de modèle Todo..


Enregistrer des Todos

Maintenant que notre modèle et notre adaptateur de modèle sont en place, nous pouvons commencer par la logique de l'application. Commençons par ajouter des éléments à notre liste de tâches.

Editez la méthode de sauvegarde sur l'adaptateur pour enregistrer une instance de tâche

Lorsque vous travaillez avec des données, le premier endroit où vous devriez aller est l’adaptateur de modèle. Nous devons pouvoir sauvegarder une instance de notre modèle Todo dans notre tableau geddy.todos. Alors ouvre-toi lib / model_adapters / todo.js et ajoutez une méthode de sauvegarde:

var Todo = new (function () this.save = function (todo, opts, callback) if (type de callback! = 'fonction') callback = function () ; todo.saved = true; geddy. todos.push (todo); retourne le rappel (null, todo);) ();

Tout ce que nous avons à faire est de définir la propriété sauvée de l'instance sur true et de pousser l'élément dans le tableau geddy.todos. Dans Node, il est préférable d'effectuer toutes les E / S de manière non bloquante, c'est donc une bonne idée de prendre l'habitude d'utiliser des rappels pour transmettre des données. Pour ce tutoriel, cela n'a pas beaucoup d'importance, mais plus tard, quand nous commencerons à persister, cela nous sera utile. Vous remarquerez que nous nous sommes assurés que le rappel est une fonction. Si nous ne le faisons pas et utilisons save sans rappel, nous obtiendrions une erreur. Passons maintenant à l'action de création du contrôleur.

Modifier l'action de création pour enregistrer une instance de tâche

Allez-y et jetez un oeil à la créer action dans app / controllers / todos.js:

this.create = function (req, resp, params) // Sauvegarde la ressource, puis affiche la page d'index this.redirect (controller: this.name); ;

Assez simple, non? Geddy vous en a parlé. Alors modifions un peu:

this.create = fonction (req, resp, params) var self = ceci, todo = geddy.model.Todo.create (titre: params.title, id: geddy.string.uuid (10), statut: 'ouvert '); todo.save (function (err, data) if (err) params.errors = err; self.transfer ('add'); else self.redirect (controller: self.name);) ; ;

Tout d'abord, nous créons une nouvelle instance du modèle Todo avec geddy.model.Todo.create, en transmettant le titre que notre formulaire nous affichera et en configurant les valeurs par défaut pour l'identifiant et le statut.

Ensuite, nous appelons la méthode de sauvegarde créée sur l'adaptateur de modèle et redirigeons l'utilisateur vers la route / todos. Si cela ne passe pas la validation, ou si nous obtenons une erreur, nous utilisons le contrôleur transfert méthode de transfert de la demande vers le ajouter action.

Éditez add.html.ejs

Il est maintenant temps de configurer le modèle d’ajout. Jeter un coup d'œil à app / views / todos / add.html.ejs, ça devrait ressembler à ça:

Paramètres

    <% for (var p in params) %>
  • <%= p + ': ' + params[p]; %>
  • <% %>

Nous n'aurons pas besoin de ça

    pour notre cas d'utilisation, nous allons donc nous en débarrasser pour l'instant. Faire votre add.html.ejs ressemble à ca:

    <%= partial('_form', params: params); %>

    Une introduction aux partiels

    Les partiels vous permettent de partager facilement le code entre vos modèles..

    Vous remarquerez que nous utilisons un partiel dans ce modèle. Les partiels vous permettent de partager facilement le code entre vos modèles. Nos modèles d'ajout et d'édition utiliseront tous deux le même formulaire. Nous allons donc créer ce formulaire partiellement maintenant. Créer un nouveau fichier dans le vues / todos / répertoire appelé _form.html.ejs. Nous utilisons un trait de soulignement pour indiquer facilement si ce modèle est partiel. Ouvrez-le et ajoutez dans ce code:

    <% var isUpdate = params.action == 'edit' , formTitle = isUpdate ? 'Update this To Do Item' : 'Create a new To Do Item' , action = isUpdate ? '/todos/' + todo.id + '?_method=PUT' : '/todos' , deleteAction = isUpdate ? '/todos/' + todo.id + '?_method=DELETE' :", btnText = isUpdate ? 'Update' : 'Add' , doneStatus = isUpdate ? 'checked' :", titleValue = isUpdate ? todo.title :", errors = params.errors; %> 
    <%= formTitle %>
    <% if (errors) %>

    <% for (var p in errors) %>

    <%= errors[p]; %>
    <% %>

    <% %>
    <% if (isUpdate) %>
    <% %>
    <% if (isUpdate) %> <% %>

    Whoa, ça fait beaucoup de code! Voyons si nous pouvons marcher à travers. Étant donné que deux modèles différents vont utiliser cette version partielle, nous devons nous assurer que le formulaire est correct dans les deux cas. La plupart de ce code est en fait un passe-partout tiré de Bootstrap de Twitter. C’est ce qui permet à cette application d’être si belle dès le départ (et sur les appareils mobiles aussi!).

    Pour rendre cette application encore meilleure, vous pouvez utiliser le fichier CSS fourni dans le téléchargement de l'application de démonstration..

    La première chose que nous avons faite a été de configurer certaines variables que nous pouvons utiliser. dans le ajouter l'action que nous passons un params objet vers le bas dans le modèle répondre appel de méthode. Cela nous donne quelques éléments - il nous indique quel contrôleur et quelle action cette demande a été acheminée, ainsi que tous les paramètres de requête qui ont été transmis dans l'URL. Nous avons mis en place le isUpdate variable pour voir si nous sommes actuellement sur l'action de mise à jour, puis nous avons configuré quelques variables supplémentaires pour nettoyer notre code d'affichage..

    À partir de là, tout ce que nous avons fait est de créer un formulaire. Si nous sommes sur l'action add, nous rendons simplement le formulaire tel quel. Si nous sommes sur l'action d'édition, nous remplissons le formulaire pour permettre à l'utilisateur de mettre à jour les champs..

    Notez que le formulaire enverra un POSTER demande au / todos / avec un _method = PUT paramètre. Geddy utilise le paramètre de substitution de méthode standard pour vous permettre d’envoyer METTRE et EFFACER demandes du navigateur sans avoir à utiliser JavaScript. (au moins au début!)

    Le dernier petit détail que nous devons examiner est le bouton «Supprimer». Nous utilisons html5 formaction attribut pour changer l'action pour ce formulaire. Vous remarquerez que ce bouton est formaction envoie un POSTER demande jusqu'à la / todos /: id itinéraire avec un _method = DELETE paramètre. Cela va frapper le retirer action sur le contrôleur, que nous verrons plus tard.

    Redémarrez votre serveur (geddy) et visitez http: // localhost: 4000 / todos / add pour voir votre modèle en action. Créez une tâche lorsque vous y êtes.


    Liste de tous les Todos

    Maintenant que nous avons ajouté des tâches à l'utilisateur dans notre tableau geddy.todos, nous devrions probablement les répertorier quelque part. Commençons par le tout méthode dans l'adaptateur de modèle.

    Modifiez la méthode all sur l'adaptateur pour répertorier tous les tâches.

    Ouvrons lib / model_adapters / todo.js encore et ajouter un toute la méthode juste au-dessus de laméthode 'save':

    this.all = fonction (rappel) rappel (null, geddy.todos); 

    C’est probablement la méthode d’adaptateur de modèle la plus simple que nous créerons aujourd’hui. Tout ce qu’elle fait, c’est accepter un rappel et l’appeler avec une erreur (ce qui est toujours nul, nous mettrons à jour cette méthode dans le prochain tutoriel), et geddy.todos.

    Éditez l'action d'index pour afficher tous les todos

    S'ouvrir /app/controllers/todos.js encore une fois et jetez un oeil à la indice action. Ça devrait ressembler a quelque chose comme ca:

    this.index = fonction (req, resp, params) this.respond (params: params); ;

    Cette partie est très simple, nous utilisons simplement le tout méthode que nous venons de définir sur le modèle-adaptateur pour obtenir tous les faires et les rendre:

    this.index = fonction (req, resp, params) var self = this; geddy.model.adapter.Todo.all (function (err, todos) self.respond (params: params, todos: todos);); ;

    Voilà pour le contrôleur, maintenant sur la vue.

    Editer index.html.ejs

    Jetez un coup d’oeil à /app/views/todos/index.html.ejs, ça devrait ressembler à ça:

    Paramètres

      <% for (var p in params) %>
    • <%= p + ': ' + params[p]; %>
    • <% %>

    Cela ressemble beaucoup au modèle add.html.ejs, non. Encore une fois, nous n’aurons pas besoin du paramétrage standard, donc supprimez-le et donnez à votre modèle index.html.ejs l’apparence suivante:

    Liste de choses à faire

    Créer une nouvelle tâche

    <% if (todos && todos.length) %> <% for (var i in todos) %>

    / edit "><%= todos[i].title; %>

    <%= todos[i].status; %>

    <% %> <% %>

    Celui-ci est également assez simple, mais cette fois, nous avons une boucle dans notre modèle. Dans l'en-tête, nous avons ajouté un bouton pour ajouter de nouvelles tâches. Dans la boucle, nous générons une ligne pour chaque faire, affichant son titre (comme un lien vers son modifier page), et son statut.

    Pour le vérifier, allez à http: // localhost: 4000 / todos.


    Editer un Todo

    Maintenant que nous avons un lien vers le modifier page, nous devrions probablement le faire fonctionner!

    Créer une méthode de chargement dans l'adaptateur de modèle

    Ouvrez à nouveau votre adaptateur de modèle (/lib/model_adapters/todo.js). Nous allons ajouter dans un charge méthode afin que nous puissions charger un spécifique faire et utilisez-le dans notre page d'édition. Peu importe où vous l'ajoutez, mais pour l'instant, mettons-le entre le tout méthode et la enregistrer méthode:

    this.load = function (id, callback) for (var i dans geddy.todos) if (geddy.todos [i] .id == id) return callback (null, geddy.todos [i]);  callback (message: "To Do not found", null); ;

    Cette méthode de chargement prend un identifiant et un rappel. Il parcourt les éléments dans geddy.todos et vérifie si l'élément actuel est identifiant correspond au passé identifiant. Si c'est le cas, il appelle le rappel, en passant le faire article en arrière. S'il ne trouve pas de correspondance, il appelle le rappel avec une erreur. Maintenant, nous devons utiliser cette méthode dans l'action show de l'automate todos.

    Editer l'action edit pour trouver une tâche

    Ouvrez votre todos contrôleur à nouveau et jetez un oeil à c'est modifier action. Ça devrait ressembler a quelque chose comme ca:

    this.edit = function (req, resp, params) this.respond (params: params); ;

    Utilisons la méthode de chargement que nous venons de créer:

    this.edit = fonction (req, resp, params) var self = this; geddy.model.Todo.load (params.id, fonction (err, todo) self.respond (params: params, todo: todo);); ;

    Nous ne faisons que charger la tâche et l'envoyer au modèle à restituer. Alors jetons un coup d'oeil au modèle.

    Éditez edit.html.ejs

    S'ouvrir /app/views/todos/edit.html.ejs. Encore une fois, nous n’avons plus besoin du paramétrage standard, supprimons-le. Faire votre edit.html.ejs ressemble à ca:

    <%= partial('_form', params: params, todo: todo); %>

    Cela devrait ressembler beaucoup à la add.html.ejs fichier que nous venons d'éditer. Vous remarquerez que nous envoyons un faire objet vers le bas ainsi que les params cette fois. La chose intéressante est que, puisque nous avons déjà écrit le partiel, c’est tout ce que nous avons à faire pour que la page de modification s’affiche correctement..

    Redémarrez le serveur, créez un nouveau faire et cliquez sur le lien pour voir comment cela fonctionne. Faisons en sorte que le bouton de mise à jour fonctionne!

    Editer la méthode de sauvegarde dans l'adaptateur de modèle

    Ouvrez à nouveau l'adaptateur de modèle et trouvez le enregistrer méthode. nous allons ajouter un peu pour que nous puissions économiser sur l'existant faires. Faites-le ressembler à ceci:

    this.save = function (todo, opts, callback) if (type de callback! = 'fonction') callback = function () ;  var todoErrors = null; for (var i dans geddy.todos) // s'il y en a déjà, enregistrez-le si (geddy.todos [i] .id == todo.id) geddy.todos [i] = todo; todoErrors = geddy.model.Todo.create (todo) .errors; renvoyer un rappel (todoErrors, todo);  todo.saved = true; geddy.todos.push (todo); retourne le rappel (null, todo); 

    Cette boucle sur tous les todo en geddy.todos et si le identifiant est déjà là, ça remplace ça faire avec le nouveau faire exemple. Nous travaillons ici pour nous assurer que nos validations fonctionnent à la fois sur update et sur create. Pour ce faire, nous devons tirer le meilleur parti possible. les erreurs propriété hors d'une nouvelle instance de modèle et la renvoyer dans le rappel. S'il réussit les validations, ce sera simplement indéfini et notre code l'ignorera. Si ça ne passe pas, todoErrors sera un tableau d'erreurs de validation.

    Maintenant que nous avons cela en place, travaillons sur notre contrôleur mettre à jour action.


    Modifiez l'action de mise à jour pour rechercher une tâche, modifier le statut et l'enregistrer.

    Allez-y et ouvrez le contrôleur à nouveau et trouvez l'action 'update', elle devrait ressembler à ceci:

    this.update = function (req, resp, params) // Enregistrez la ressource, puis affichez la page d'élément this.redirect (controller: this.name, id: params.id); ;

    Vous voudrez l'éditer pour qu'il ressemble à ceci:

    this.update = function (req, resp, params) var self = this; geddy.model.adapter.Todo.load (params.id, fonction (err, todo) todo.status = params.status; todo.title = params.title; todo.save (fonction (err, data) if err) params.errors = err; self.transfer ('edit'); else self.redirect (controller: self.name););); ;

    Ce que nous faisons ici charge la demande faire, éditer certaines de ses propriétés et enregistrer le faire encore. Le code que nous venons d'écrire dans le modèle d'adaptateur devrait gérer le reste. Si nous obtenons une erreur en retour, cela signifie que les nouvelles propriétés n'ont pas passé la validation. Nous allons donc transférer la demande à la requête. modifier action. Si nous ne recevons pas d'erreur en retour, nous redirigerons simplement la demande vers le indice action.

    Allez-y et essayez le. Redémarrez le serveur, créez un nouveau faire, cliquez sur son lien de modification, changez le statut en terminé, et voir qu'il est mis à jour dans le indice. Si vous voulez vérifier que vos validations fonctionnent, essayez de changer le Titre à quelque chose de moins de 5 caractères.

    Maintenant, faisons fonctionner ce bouton "Supprimer".


    Retrait d'un Todo

    Nous avons maintenant une application qui fonctionne bien, mais si vous commencez à l’utiliser pendant un certain temps, il vous sera difficile de trouver le faire élément que vous recherchez sur cette page d'index. Faisons en sorte que le bouton «Supprimer» fonctionne afin que nous puissions garder notre liste courte et agréable.

    Créer une méthode de suppression dans l'adaptateur de modèle

    Ouvrons à nouveau notre adaptateur de modèle, cette fois nous allons vouloir ajouter un retirer méthode là-bas. Ajoutez ceci juste après le enregistrer méthode:

    this.remove = function (id, callback) if (type de callback! = 'fonction') callback = function () ;  pour (var i dans geddy.todos) if (geddy.todos [i] .id == id) geddy.todos.splice (i, 1); retourne le rappel (null);  retourne le rappel (message: "To Do not found"); 

    Celui-ci est assez simple, il devrait ressembler beaucoup à la méthode de chargement. Il parcourt tous les fairepéché geddy.todos trouver le identifiant que nous recherchons. Il sépare ensuite cet élément du tableau et appelle le rappel. S'il ne le trouve pas dans le tableau, il appelle le rappel avec une erreur..

    Utilisons cela dans notre contrôleur maintenant.

    Editer l'action de suppression

    Ouvrez à nouveau votre contrôleur et touchez le retirer action. Ça devrait ressembler a quelque chose comme ca:

    this.remove = function (req, resp, params) this.respond (params: params); ;

    Modifiez-le pour qu'il ressemble à ceci:

    this.remove = function (req, resp, params) var self = this; geddy.model.adapter.Todo.remove (params.id, function (err) if (err) params.errors = err; self.transfer ('edit'); else self.redirect (controller: self .prénom);  ); 

    Nous passons le identifiant que nous avons reçu des params sous la forme post dans le retirer méthode que nous venons de créer. Si nous obtenons une erreur en retour, nous redirigeons vers le modifier action (nous supposons que le formulaire a envoyé la mauvaise information). Si nous ne recevons pas d'erreur en retour, envoyez simplement la demande au indice action.

    C'est tout! Avaient fini.

    Vous pouvez tester la fonction de suppression en redémarrant votre serveur, en créant un nouveau faire élément, en cliquant sur son lien, puis en cliquant sur le bouton «Supprimer». Si vous l'avez bien fait, vous devriez être de retour sur la page d'index avec cet élément supprimé.


    Les prochaines étapes

    Dans le prochain didacticiel, nous utiliserons le module génial mongodb-wrapper de http: //i.tv pour conserver notre faireest dans MongoDB. Avec Geddy, ce sera facile. tout ce que nous aurons à changer est l'adaptateur de modèle.

    Si vous avez des questions, laissez un commentaire ici ou ouvrez un problème sur github.