Completando las rutas faltates
Nos estaría faltando implementar las siguientes rutas
GET /noticias/:id
POST /noticias/:id/comentarios
PUT /noticias/:id/upvote
PUT /noticias/:id/comentarios/:idComentario/upvote
URL parameters
Comenzaremos con la primera GET /noticias/:id
la cual debe recuperar una noticia desde mongo por un id especificado. Por ejemplo: Al realizar el usuario el pedido GET /noticias/42
deberá devolversele la noticia con id 42.
Agregaremos el cuerpo para la ruta en nuestro routes.js
src/backend/routes/routes.js
El objeto req.params contiene una asociación de parametros de la ruta y los valores proporcionados para los mismos. req.params.id
contendrá entonces el valor del paraemtro :id
proporcionado por el cliente.
Notaremos que para probar dicha ruta es necesario contar con el id de una ruta previamente persistida. Dicho id es autogenerado por mongodb al momento de persistir un nuevo objeto. Podemos usar Robomongo para acceder a la información persistida en la base y obtener un id valido, aunque también es buena idea modificar la anteriormente creada ruta POST /noticias
para que devuelva el id con el que una noticia recientemente persistida en mongo.
Podemos lograr ese efecto con un sencillo cambio:
src/backend/routes/routes.js
Entonces, probar la nueva ruta con curl es un asunto sencillo. Primero creamos una nueva noticia:
$ curl -X POST \
-H 'Content-Type: application/json' \
-d '{ "title": "Noticia 1", "content": "lorem ipsum dolor sic" }' \
localhost:3001/noticias
["58b9be6f1a88980726a83c4d"]
Luego utilizamos la nueva ruta para recuperarla.
$ curl -X GET localhost:3001/noticias/58b9be6f1a88980726a83c4d
{"_id":"58b9be6f1a88980726a83c4d","title":"Noticia aaa999","content":"lorem ipsum dolor sic","__v":0,"createdAt":"2017-03-03T19:05:19.116Z","upvotes":0}
Exito!
Upvote
Proseguimos con la siguiente ruta (upvote).
src/backend/routes/routes.js
A priori la implementación parece un tanto sencilla:
- Primero recuperamos la noticia para el id que nos ha sido provisto.
- Luego incrementamos la cantidad de votosde la misma.
- La guardamos en mongo. Hacemos esto por medio del mensaje
save
. Esto es una operación asincrónica y como no queremos responder al cliente hasta que el guardado de la noticia haya sido completado correctamente (esto es una decisión de diseño) solo invocaremos ares.json(...)
una vez que la promise devuelta por el métodosave
haya sido resuelta (o sea, en elthen
de dicha promise). - Desde luego no podemos olvidarnos de manejar los errores que puedan ocurrir durante el guardado asincrónico. Para eso usamos el
catch
con la misma estrategia que antes (delegar en la funciónthen
para que express maneje el error).
Mmmm. Algo huele feo.
Algo de código repetido
Como podemos notar tanto la ruta GET /noticias/:id
como POST /noticias/:id/upvote
contienen exactamente la misma lógica para recuperar una noticia por id desde la base de datos. Este código repetido de alguna forma debería ser consolidado.
Express.js nos provee una funcionalidad llamada params
por medio de la cuál podemos preprocesar parametros antes de la invocación a nuestras rutas.
src/backend/routes/routes.js
Como podemos instruimos a express de preprocesar un parámetro llamado noticia
. Buscamos en mongo de la misma forma que lo veníamos haciendo con anterioridad, si encontramos un objeto guardamos el mismo en req.noticia
. Ahora solo resta modificar el código de nuestras rutas.
src/backend/routes/routes.js
Nombres
Es util notar que cambiamos el nombre del parametro de :id
a :noticia
. Esto fue hecho así porque el nombre id
carecía de información fuera del contexto de la ruta de noticia.
Upvote - lógica de negocio
Si bien la lógica de qué implica hacer upvote a una ruta es hoy por hoy tan sencilla como hacer noticia.upvotes++
es quizás una buena decisión de diseño extraer dicha lógica fuera del archivo de rutas y delegarla en el objeto noticia en si mismo
src/backend/routes/routes.js
Para eso agregaremos el método upvote
al schema de noticia que habíamos definido antes.
src/backend/models/Post.js
A continuación probamos que todo esté andando correctamente.
$ curl -X PUT localhost:3001/noticias/58b9be6f1a88980726a83c4d/upvote
{"_id":"58b9be6f1a88980726a83c4d","title":"Noticia aaa999","content":"lorem ipsum dolor sic","__v":0,"createdAt":"2017-03-03T19:05:19.116Z","upvotes":1}
GitHub
Como referencia dejamos el estado del proyecto en GitHub