Skip to content

Commit ec35ed9

Browse files
committed
part 4c
1 parent 3814d78 commit ec35ed9

File tree

2 files changed

+28
-44
lines changed

2 files changed

+28
-44
lines changed

src/content/4/en/part4c.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,13 +491,13 @@ usersRouter.get('/', async (request, response) => {
491491
})
492492
```
493493

494-
The [populate](http://mongoosejs.com/docs/populate.html) method is chained after the <i>find</i> method making the initial query. The parameter given to the populate method defines that the <i>ids</i> referencing <i>note</i> objects in the <i>notes</i> field of the <i>user</i> document will be replaced by the referenced <i>note</i> documents.
494+
The [populate](http://mongoosejs.com/docs/populate.html) method is chained after the <i>find</i> method making the initial query. The argument given to the populate method defines that the <i>ids</i> referencing <i>note</i> objects in the <i>notes</i> field of the <i>user</i> document will be replaced by the referenced <i>note</i> documents.
495495

496496
The result is almost exactly what we wanted:
497497

498498
![JSON data showing populated notes and users data with repetition](../../images/4/13new.png)
499499

500-
We can use the populate parameter for choosing the fields we want to include from the documents. In addition to the field <i>id</i> we are now only interested in <i>content</i> and <i>important</i>.
500+
We can use the populate method for choosing the fields we want to include from the documents. In addition to the field <i>id</i> we are now only interested in <i>content</i> and <i>important</i>.
501501

502502
The selection of fields is done with the Mongo [syntax](https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/#return-the-specified-fields-and-the-_id-field-only):
503503

src/content/4/es/part4c.md

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,10 @@ describe('when there is initially one user in db', () => {
285285
.expect('Content-Type', /application\/json/)
286286

287287
const usersAtEnd = await helper.usersInDb()
288-
expect(usersAtEnd).toHaveLength(usersAtStart.length + 1)
288+
assert.strictEqual(usersAtEnd.length, usersAtStart.length + 1)
289289

290290
const usernames = usersAtEnd.map(u => u.username)
291-
expect(usernames).toContain(newUser.username)
291+
assert(usernames.includes(newUser.username))
292292
})
293293
})
294294
```
@@ -334,34 +334,27 @@ describe('when there is initially one user in db', () => {
334334
.expect(400)
335335
.expect('Content-Type', /application\/json/)
336336

337-
expect(result.body.error).toContain('expected `username` to be unique')
338-
339337
const usersAtEnd = await helper.usersInDb()
340-
expect(usersAtEnd).toEqual(usersAtStart)
338+
assert(result.body.error.includes('expected `username` to be unique'))
339+
340+
assert.strictEqual(usersAtEnd.length, usersAtStart.length)
341341
})
342342
})
343343
```
344344

345345
El caso de prueba obviamente no pasará en este punto. Básicamente, estamos practicando [desarrollo guiado por pruebas (TDD)](https://es.wikipedia.org/wiki/Desarrollo_guiado_por_pruebas), donde las pruebas para la nueva funcionalidad se escriben antes de implementar la funcionalidad.
346346

347-
Mongoose no tiene un validador incorporado para verificar la unicidad de un campo. Podemos encontrar una solución lista para esto en el paquete npm [mongoose-unique-validator](https://www.npmjs.com/package/mongoose-unique-validator). Vamos a instalarlo:
348-
349-
```bash
350-
npm install mongoose-unique-validator
351-
```
352-
353-
Debemos realizar los siguientes cambios en el esquema definido en el archivo <i>models/user.js</i>:
347+
Las validaciones de Mongoose no proporcionan una manera directa de verificar la unicidad del valor de un campo. Sin embargo, es posible lograr la unicidad definiendo un [índice de unicidad](https://mongoosejs.com/docs/schematypes.html) para un campo. La definición se realiza de la siguiente manera:
354348

355349
```js
356350
const mongoose = require('mongoose')
357-
const uniqueValidator = require('mongoose-unique-validator') // highlight-line
358351

359352
const userSchema = mongoose.Schema({
360353
// highlight-start
361354
username: {
362355
type: String,
363356
required: true,
364-
unique: true
357+
unique: true // esto asegura la unicidad de username
365358
},
366359
// highlight-end
367360
name: String,
@@ -374,21 +367,31 @@ const userSchema = mongoose.Schema({
374367
],
375368
})
376369

377-
userSchema.plugin(uniqueValidator) // highlight-line
378-
379370
// ...
380371
```
381372

382-
Nota: al instalar la librería _mongoose-unique-validator_, es posible que encuentres el siguiente mensaje de error:
373+
Sin embargo, queremos tener cuidado al usar el índice de unicidad. Si ya hay documentos en la base de datos que violan la condición de unicidad, [no se creará ningún índice](https://dev.to/akshatsinghania/mongoose-unique-not-working-16bf). Por lo tanto, al agregar un índice de unicidad, ¡asegúrate de que la base de datos esté en un estado saludable! La prueba anterior agregó al usuario con username _root_ a la base de datos dos veces, y estos deben ser eliminados para que el índice se forme y el código funcione.
383374

384-
![error de dependencia sin resolver para mongoose unique validator](../../images/4/uniq.png)
375+
Las validaciones de Mongoose no detectan la violación del índice, y en lugar de _ValidationError_ devuelven un error del tipo _MongoServerError_. Por lo tanto, necesitamos extender el controlador de errores para ese caso:
385376

386-
La razón de esto es que en el momento de la redacción (10.11.2023), la librería aún no es compatible con la versión 8 de Mongoose. Si encuentras este error, puedes retroceder a una versión anterior de Mongoose ejecutando el comando
377+
```js
378+
const errorHandler = (error, request, response, next) => {
379+
if (error.name === 'CastError') {
380+
return response.status(400).send({ error: 'malformatted id' })
381+
} else if (error.name === 'ValidationError') {
382+
return response.status(400).json({ error: error.message })
383+
// highlight-start
384+
} else if (error.name === 'MongoServerError' && error.message.includes('E11000 duplicate key error')) {
385+
return response.status(400).json({ error: 'expected `username` to be unique' })
386+
}
387+
// highlight-end
387388

388-
```
389-
npm install [email protected]
389+
next(error)
390+
}
390391
```
391392

393+
Luego de estos cambios, las pruebas pasaran.
394+
392395
También podríamos implementar otras validaciones en la creación de usuarios. Podríamos comprobar que el nombre de usuario es lo suficientemente largo, que el nombre de usuario solo consta de caracteres permitidos o que la contraseña es lo suficientemente segura. La implementación de estas funcionalidades se deja como ejercicio opcional.
393396

394397
Antes de continuar, agreguemos una implementación inicial de un controlador de ruta que devuelva todos los usuarios en la base de datos:
@@ -446,25 +449,6 @@ notesRouter.post('/', async (request, response) => {
446449
})
447450
```
448451

449-
El esquema de las notas también deberá cambiar cómo a continuación, en nuestro archivo models/note.js:
450-
451-
```js
452-
const noteSchema = new mongoose.Schema({
453-
content: {
454-
type: String,
455-
required: true,
456-
minlength: 5
457-
},
458-
important: Boolean,
459-
// highlight-start
460-
user: {
461-
type: mongoose.Schema.Types.ObjectId,
462-
ref: 'User'
463-
}
464-
//highlight-end
465-
})
466-
```
467-
468452
Vale la pena notar que el objeto <i>user</i> también cambia. El <i>id</i> de la nota se almacena en el campo <i>notes</i> del objeto <i>user</i>:
469453

470454
```js
@@ -507,13 +491,13 @@ usersRouter.get('/', async (request, response) => {
507491
})
508492
```
509493

510-
El método [populate](http://mongoosejs.com/docs/populate.html) se encadena después de que el método <i>find</i> realiza la consulta inicial. El parámetro dado al método populate define que los <i>ids</i> que hacen referencia a objetos <i>note</i> en el campo <i>notes</i> del documento <i>user</i> serán reemplazados por los documentos de <i>note</i> referenciados.
494+
El método [populate](http://mongoosejs.com/docs/populate.html) se encadena después de que el método <i>find</i> realiza la consulta inicial. El argumento dado al método populate define que los <i>ids</i> que hacen referencia a objetos <i>note</i> en el campo <i>notes</i> del documento <i>user</i> serán reemplazados por los documentos de <i>note</i> referenciados.
511495

512496
El resultado es casi exactamente lo que queríamos:
513497

514498
![datos JSON en el navegador mostrando datos de notas y usuarios repetidos](../../images/4/13new.png)
515499

516-
Podemos usar el parámetro populate para elegir los campos que queremos incluir de los documentos. Además del campo *id*, ahora solo nos interesan *content* e *important*.
500+
Podemos usar el método populate para elegir los campos que queremos incluir de los documentos. Además del campo *id*, ahora solo nos interesan *content* e *important*.
517501

518502
La selección de campos se realiza con la [sintaxis](https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/#return-the-specified-fields-and-the-_id-field-only) de Mongo:
519503

0 commit comments

Comments
 (0)