Actualizar usuarios correctamente es fundamental para cualquier API moderna. Aquí aprenderás, paso a paso, a implementar el método PUT siguiendo principios de un CRUD, garantizando una gestión robusta y flexible de los datos.
¿Qué es el método put y cómo completa el ciclo CRUD?
Todo CRUD efectivo incluye crear, leer, actualizar y eliminar. Put es el método que permite la actualización. Al implementar “put” en los endpoints, logras que los recursos sean modificables según lo necesite la lógica de negocio. Puedes replicarlo para usuarios, perfiles, grupos o compañías según lo necesites.
Put utiliza el parámetro ID para identificar qué recurso actualizar.
Es indispensable enviar el ID para realizar la actualización.
Permite recibir datos en el “body”, igual que un “post”, para aplicar cambios específicos.
¿Cómo automatizar el ID al crear nuevos usuarios?
Al automatizar un ID, evitas errores y garantizas unicidad:
Inicialmente puedes asignar el ID como el tamaño del array más uno, convertido siempre a string.
Es preferible sobrescribir cualquier ID que el usuario envíe desde el backend, garantizando así la validez.
Para evitar duplicados tras eliminar usuarios, puedes usar un ID basado en el timestamp:
const newUser = {
...body,
id: new Date().getTime().toString(),
}
Esta solución es temporal hasta usar una base de datos real, donde la lógica será más sofisticada.
¿Cuáles son las diferencias clave entre put y patch para actualizar datos?
Al actualizar, existen dos opciones principales: put y patch.
Put suele exigir enviar todos los campos de la entidad; si tienes veinte propiedades, debes enviarlas todas.
Patch permite actualizar solo los campos que cambian, enviando solo esos datos.
En la práctica habitual de APIs, put ya permite flexibilidad para actualizar solo los campos enviados.
¿Cómo se implementa update user utilizando JavaScript y qué validaciones son fundamentales?
El endpoint para actualizar usuarios utiliza dos argumentos:
Un parámetro (por ejemplo, /user/:id) para identificar el usuario.
Al actualizar, solo se sobrescriben los campos enviados.
Si el ID no existe, la función retorna un mensaje informativo.
La respuesta habitual es el usuario actualizado completo y un status 200.
¿Cómo debes validar los datos al crear o actualizar usuarios?
La validación evita inconsistencias como usuarios duplicados o emails incorrectos:
Es esencial comprobar que el email tiene el formato correcto (incluye @ y dominio).
Puedes usar expresiones regulares para esta validación.
Aún no se implementaron reglas estrictas, pero es la base para robustecer la API.
¿Tienes ideas para validar correos o sugerencias propias para mejorar el sistema de IDs? Comparte tus propuestas y sigamos aprendiendo nuevos retos del desarrollo de APIs.
El método PUT es ideal para actualizar un recurso completo, ya que requiere que se envíen todos los campos de la entidad, mientras que PATCH se utiliza para actualizaciones parciales, permitiendo modificar solo los campos que desees.
Si necesitas actualizar solo algunos atributos del usuario, PATCH es más eficiente. Sin embargo, si deseas reemplazar la entidad completa, utiliza PUT. La elección depende del contexto de la operación que estés realizando.
Esto mismo venía a comentar, totalmente de acuerdo y según los estándares es así como tu lo dices, en este caso en lugar de usar el método PUT, se debió usar el PATCH
Yo prefiero usar randomUUID para los ids, aca mi solución
import{Body,Controller,Delete,Get,Param,Post,Put}from'@nestjs/common';import{ randomUUID }from'crypto';interfaceUser{id: string;name: string;email: string;}interfaceResponse{message: string; data?:User|User[];}@Controller('users')exportclassUsersController{privateusers:User[]=[{id:'1',name:'Maria Luna',email:'maria.luna@example.com',},{id:'2',name:'Carmen Lopez',email:'carmen.lopez@example.com',},{id:'3',name:'Vero Cornejo',email:'vero.cornejo@example.com',},]; @Get()getUsers():Response{constresponse:Response={message:'Users found successfully',}; response.data=this.users;return response;} @Get(':id')findUser(@Param('id') id: string):Response{const result =this.users.find((user)=> user.id=== id);constresponse:Response={message:'User found successfully',};if(!result){ response.message='User not found';return response;} response.data= result;return response;} @Post()createUser(@Body() body:Omit<User,'id'>):Response{this.users.push({...body,id:randomUUID(),});return{message:'User created successfully',};} @Delete(':id')deleteUser(@Param('id') id: string):Response{const position =this.users.findIndex((user)=> user.id=== id);if(position ===-1){return{message:'User not found',};}this.users.splice(position,1);return{message:'User deleted successfully',};} @Put(':id')updateUser(@Param('id') id: string, @Body() body:Omit<User,'id'>):Response{const position =this.users.findIndex((user)=> user.id=== id);if(position ===-1){return{message:'User not found',};}const updatedUser ={...this.users[position],...body,};this.users[position]= updatedUser;return{message:'User updated successfully',};}}
En el contexto de NestJS, cuando agregas un nuevo endpoint, necesitas reiniciar el servidor para que los cambios sean reflejados en la aplicación. Esto es típico en entornos de desarrollo. Sin embargo, puedes utilizar herramientas como nodemon, que permite el reinicio automático del servidor cada vez que detecta cambios en los archivos del proyecto. Esto mejora la eficiencia al evitar el reinicio manual constante. Configurar nodemon es sencillo; simplemente debes instalarlo y modificar el script de inicio en tu archivo package.json.
Pero para que? En las ultimas versiones de node eso ya lo hace, simplemente agregando el --watch en el package.json y ya
Concepto: Un DTO es una clase que define la "forma" de los datos que esperas. Si el usuario envía algo que no cumple las reglas, NestJS rechaza la petición antes de que llegue a tu servicio. 🚫
1. Instalación de Dependencias 📦
Necesitas estas dos librerías (ejecuta en tu terminal): npm i class-validator class-transformer
2. Creación del DTO (create-user.dto.ts) 📝
Usa decoradores para definir las reglas de cada campo:
TypeScript
import{IsString,IsEmail,IsNotEmpty,MinLength}from'class-validator';exportclassCreateUserDto{ @IsString() @IsNotEmpty()name: string; @IsEmail({},{message:'El formato del correo es inválido 📧'})email: string; @IsString() @MinLength(6)password: string;}
3. El Truco para Actualizaciones (update-user.dto.ts) 🔄
Para el método PUT, no quieres repetir código. Usa PartialType de @nestjs/mapped-types. Esto hace que todos los campos del CreateDTO sean opcionales automáticamente.
Para que esto funcione, debes decirle a NestJS que use el ValidationPipe en toda la aplicación:
TypeScript
// En main.tsapp.useGlobalPipes(newValidationPipe({whitelist:true,// Borra campos que no estén en el DTO 🧹forbidNonWhitelisted:true,// Lanza error si envían campos extra 🚫transform:true,// Convierte tipos automáticamente ⚡}));
💡 ¿Por qué usar esto? (Beneficios)
Seguridad: Evitas que te inyecten campos maliciosos (gracias a whitelist). 🔒
Código Limpio: Tu controlador ya no tiene 20 if validando correos o nombres. 🧹
Documentación: El DTO sirve como contrato de qué datos acepta tu API. 📜
Error 400 Automático: Si el email está mal, Nest responde con un 400 Bad Request detallado sin que tú escribas una sola línea de lógica de error. 🚥
🔄 Actualización de Recursos: PUT y PATCH
🛠️ ¿Cómo funciona la actualización?
El proceso de actualizar completa el ciclo CRUD. Para que sea exitoso, necesitas dos cosas:
Identificador (@Param): El ID en la URL para saber a quién editar. 🆔
Datos (@Body): Los cambios que quieres aplicar. 📦
⚖️ PUT vs. PATCH: ¿Cuál elegir?
PUT: Teóricamente, reemplaza todo el objeto. Si olvidas un campo, podría borrarse o quedar nulo. ⚠️
PATCH: Actualiza solo los campos que envías. Es más eficiente para cambios parciales. ⚡
En la práctica: Muchos desarrolladores usan PUT con la flexibilidad de PATCH usando el Spread Operator en JavaScript.
💡 El Truco del "Merge" (Fusión de Datos)
Para actualizar correctamente sin perder información que no se envió en el body, usa esta lógica en tu servicio:
JavaScript
const currentData = users[userIndex];users[userIndex]={...currentData,// Datos viejos...changes,// Datos nuevos (sobrescriben a los viejos)};
🆔 Automatización de IDs (Provisional)
Mientras no uses una base de datos real (SQL/NoSQL), puedes generar IDs únicos así:
Opción A (Simple): array.length + 1. (Cuidado: si borras usuarios, los IDs pueden repetirse). 🔢
Opción B (Segura): new Date().getTime().toString(). Usa el timestamp actual; es casi imposible que se repita. ⏱️
🛡️ Validaciones Fundamentales
No confíes en lo que envía el usuario. Antes de guardar, verifica:
Formato de Email: Usa Regex o librerías para asegurar que tenga @ y dominio. 📧
Existencia: Si el findIndex devuelve -1, dispara un 404 Not Found de inmediato. 🚫
Unicidad: Antes de actualizar un email, revisa que otro usuario no lo tenga ya registrado. 🔍
🌟 Resumen para el desarrollador
Status Code: Devuelve siempre un 200 OK junto con el objeto ya actualizado. ✅
Seguridad: Ignora cualquier ID que el usuario envíe en el @Body; usa siempre el que viene en el @Param. 🛡️
Hola a todos. Este es mi reto. He creado un script con expresiones regulares para validar si el formato de email es correcto
El problema inicial con la sobrescritura del id al usar el spread sobre body también estaba relacionado con nuestro manejo en TypeScript.
Lo que hice fue omitir el id del tipo User y tipar el body con este nuevo tipo. Luego, en Insomnia, simplemente no enviamos el id, ya que el frontend no debería indicar qué id tendrá el nuevo usuario. Con esto, todo encaja.
type User={id: string;name: string;email: string;};type CreateUserBody=Omit<User,'id'>// Más adelante en el @Post @Post()createUser(@Body() body:CreateUserBody){const id = crypto.randomUUID()const user ={...body, id}this.users.push(user)return body
}
Tengo una duda, ¿Por qué cada vez que agregamos un endpoint debemos bajar el server y volverlo a subir? ¿No hay forma que se haga automático, como cuando uno trabaja con nodemon?
Saludos compañero; No es obligatorio, NestJS cuenta con un script que puedes ejecutar en la consola, el cual actualiza la conexión al detectar cambios en el código:
npm run start:dev
Pero el bajar el server y volverlo a subir es una buena practica, dado que hay ciertos cambios o errores que pueden saturar tu consola con información, o tu conexión, impidiendo la renovar al detectar nuevos cambios.