-
Notifications
You must be signed in to change notification settings - Fork 30
/
09s-creating-a-meteor-package.md.erb
219 lines (164 loc) · 7.79 KB
/
09s-creating-a-meteor-package.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
---
title: Creando un paquete Meteor
slug: creating-a-meteor-package
date: 0009/01/02
number: 9.5
points: 10
sidebar: true
photoUrl: http://www.flickr.com/photos/rxb/7779426142/
photoAuthor: Richard
contents: Escribiremos un paquete Meteor para nuestra aplicación de forma local.|Escribiremos tests para nuestro paquete.|Publicaremos el paquete en el repositorio Atmosphere.
paragraphs: 22
---
Durante nuestro trabajo en los errores, hemos construido un modelo reutilizable, ¿por qué no ponerlo dentro de un paquete y compartirlo con el resto de la comunidad Meteor?
Para empezar, tenemos que asegurarnos de que tenemos una cuenta de desarrollador Meteor. Puedes hacerte una en [meteor.com](meteor.com), pero es muy probable que ya lo hayas hecho ¡cuando te registraste para el libro! En cualquier caso, deberías saber cuál es tu nombre de usuario, porque lo utilizaremos bastante durante este capítulo.
En este capítulo usaremos `tmeasday` como usuario -- puedes cambiarlo por el tuyo.
En primer lugar, necesitamos crear una estructura de carpetas para nuestro paquete. Podemos usar el comando `meteor create --package tmeasday:errors` para conseguirla. Fíjate que Meteor ha creado una carpeta llamada `packages/tmeasday:errors/`, con algunos ficheros dentro. Comenzaremos por editar `package.js`, el archivo que informa a Meteor de cómo debe utilizar el paquete, y los símbolos y funciones que exporta.
~~~js
Package.describe({
name: "tmeasday:errors",
summary: "A pattern to display application errors to the user",
version: "1.0.0"
});
Package.onUse(function (api, where) {
api.versionsFrom('0.9.0');
api.use(['minimongo', 'mongo-livedata', 'templating'], 'client');
api.addFiles(['errors.js', 'errors_list.html', 'errors_list.js'], 'client');
if (api.export)
api.export('Errors');
});
~~~
<%= caption "packages/tmeasday:errors/package.js" %>
Cuando desarrollamos un paquete para su uso en el mundo-real, es una buena práctica rellenar la sección `Package.describe` con la URL del repositorio Git (como por ejemplo, `https://github.com/tmeasday/meteor-errors.git`). De esta manera, los usuarios pueden acceder al código fuente, y (si usas GitHub) ver el README del paquete en Atmosphere.
Vamos a añadir al paquete los tres archivos que se pasan en la llamada a `add_files`. Podemos usar los mismos que tenemos para Microscope, haciendo solo, unos pequeños cambios para los espacios de nombres y para dejar la API un poco más limpia:
~~~js
Errors = {
// Local (client-only) collection
collection: new Mongo.Collection(null),
throw: function(message) {
Errors.collection.insert({message: message, seen: false})
}
};
~~~
<%= caption "packages/tmeasday:errors/errors.js" %>
~~~html
<template name="meteorErrors">
<div class="errors">
{{#each errors}}
{{> meteorError}}
{{/each}}
</div>
</template>
<template name="meteorError">
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert">×</button>
{{message}}
</div>
</template>
~~~
<%= caption "packages/tmeasday:errors/errors_list.html" %>
~~~js
Template.meteorErrors.helpers({
errors: function() {
return Errors.collection.find();
}
});
Template.meteorError.rendered = function() {
var error = this.data;
Meteor.setTimeout(function () {
Errors.collection.remove(error._id);
}, 3000);
};
~~~
<%= caption "packages/tmeasday:errors/errors_list.js" %>
### Probando el paquete con Microscope
Vamos a probar el paquete localmente con Microscope para asegurarnos de que nuestros cambios funcionan. Para enlazar el paquete en nuestro proyecto, ejecutaremos `meteor add tmeasday:errors`. A continuación, debemos eliminar los archivos a los que reemplaza el nuevo paquete:
~~~bash
rm client/helpers/errors.js
rm client/templates/includes/errors.html
rm client/templates/includes/errors.js
~~~
<%= caption "Eliminando los archivos antiguos" %>
Otra cosa que debemos hacer son algunos pequeños cambios en el código de la aplicación para que use la API correcta:
~~~html
{{> header}}
{{> meteorErrors}}
~~~
<%= caption "client/templates/application/layout.html" %>
~~~js
Meteor.call('postInsert', post, function(error, result) {
if (error) {
// display the error to the user
Errors.throw(error.reason);
// show this result but route anyway
if (result.postExists)
Errors.throw('This link has already been posted');
~~~
<%= caption "client/templates/posts/post_submit.js" %>
~~~js
Posts.update(currentPostId, {$set: postProperties}, function(error) {
if (error) {
// display the error to the user
Errors.throw(error.reason);
~~~
<%= caption "client/templates/posts/post_edit.js" %>
<%= highlight "4,8" %>
<%= scommit "9-5-1", "Creado y enlazado un paquete básico." %>
Una vez hechos estos cambios, deberíamos ver el mismo comportamiento que teníamos con el código sin empaquetar.
### Escribiendo Tests
El primer paso en el desarrollo de un paquete es probarlo contra una aplicación, pero el siguiente es escribir un conjunto de tests que evalúen adecuadamente el comportamiento del paquete. Meteor incluye Tinytest, que permite ejecutar este tipo de pruebas de forma fácil y, de esta forma, tener la conciencia tranquila cuando compartimos el paquete con los demás.
Vamos a crear un archivo que usa Tinytest para ejecutar tests contra el código de los errores.
~~~js
Tinytest.add("Errors - collection", function(test) {
test.equal(Errors.collection.find({}).count(), 0);
Errors.throw('A new error!');
test.equal(Errors.collection.find({}).count(), 1);
Errors.collection.remove({});
});
Tinytest.addAsync("Errors - template", function(test, done) {
Errors.throw('A new error!');
test.equal(Errors.collection.find({}).count(), 1);
// render the template
UI.insert(UI.render(Template.meteorErrors), document.body);
Meteor.setTimeout(function() {
test.equal(Errors.collection.find({}).count(), 0);
done();
}, 3500);
});
~~~
<%= caption "packages/tmeasday:errors/errors_tests.js" %>
Con estos tests comprobamos que las funciones básicas de `Meteor.Errors` funcionan correctamente, así como que el código `mostrado` en la plantilla sigue funcionando bien.
No vamos a cubrir los aspectos específicos sobre cómo escribir tests de paquetes (porque la API todavía no está acabada y podría cambiar mucho), pero viendo el código, puedes hacerte una idea cómo funciona.
Para decirle a Meteor que ejecute los tests, añadimos este código a `package.js`
~~~js
Package.onTest(function(api) {
api.use('tmeasday:errors', 'client');
api.use(['tinytest', 'test-helpers'], 'client');
api.addFiles('errors_tests.js', 'client');
});
~~~
<%= caption "packages/tmeasday:errors/package.js" %>
<%= scommit "9-5-2", "Tests añadidos al paquete." %>
Ya podemos ejecutar los tests con:
~~~bash
meteor test-packages tmeasday:errors
~~~
<%= caption "Terminal" %>
<%= screenshot "s7-1", "Pasando todos los tests" %>
### Publicando el paquete
Ahora, queremos liberar el paquete y ponerlo a disposición de todo el mundo. Para ello tendremos que subirlo al servidor de paquetes de Meteor y, hacerlo miembro del repositorio Atmosphere.
Afortunadamente, es muy fácil. Entramos en el directorio del paquete, y ejecutamos `meteor publish --create`:
~~~bash
cd packages/tmeasday:errors
meteor publish --create
~~~
<%= caption "Terminal" %>
Ahora que hemos publicado el paquete, podemos eliminarlo del proyecto y luego añadirlo de nuevo directamente:
~~~bash
rm -r packages/errors
meteor add tmeasday:errors
~~~
<%= caption "Terminal (ejecutar desde el directorio raíz de la aplicación)" %>
<%= scommit "9-5-4", "Paquete eliminado del árbol de desarrollo." %>
Ahora debemos ver a Meteor descargar nuestro paquete por primera vez. ¡Bien hecho!
Como de costumbre, asegúrate de deshacer los cambios antes de continuar (o mantenerlos, teniéndolos en cuenta en el resto del libro).