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.
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..
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:
Votre config / router.js
devrait également avoir cette annexe:
routeur.resource ('todos');
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 faire
ont. 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..
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:
Tout bon? Bon, continuons.
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 faire
s, 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 faire
s et en l’enregistrant comme modèle dans geddy. Définissons quelques propriétés pour notre faire
s. 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 faire
s aura un titre, un identifiant et un statut, et les trois seront nécessaires. Maintenant fixons quelques validations pour notre faire
s.
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..
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.
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 faire
s. Rappelez-vous que ceci est dans la mémoire de votre application, donc il disparaîtra au redémarrage du serveur..
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.
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..
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.
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.
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.
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); %>
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; %>
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.
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.
Ouvrons lib / model_adapters / todo.js
encore et ajouter un toute la méthode juste au-dessus de la
mé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
.
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 faire
s 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.
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:
<% if (todos && todos.length) %> <% for (var i in todos) %>Liste de choses à faire
Créer une nouvelle tâche<% %> <% %>/ 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.
Maintenant que nous avons un lien vers le modifier
page, nous devrions probablement le faire fonctionner!
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.
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.
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!
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 faire
s. 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.
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".
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.
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 faire
pé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.
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é.
Dans le prochain didacticiel, nous utiliserons le module génial mongodb-wrapper de http: //i.tv pour conserver notre faire
est 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.