Regístrate para acceder a más de 15 cursos gratuitos de programación con un simulador

Creación de CRUD en Fastify JS: Desarrollo web

A pesar de la gran variedad de sitios web, prácticamente todo el desarrollo web se puede reducir a las operaciones CRUD. En esta lección, las conoceremos en detalle.

¿Qué es CRUD?

CRUD es un término ampliamente difundido que denota las cuatro operaciones estándar que se realizan con cualquier entidad. Consideremos el siguiente ejemplo:

  • Crear (Create) — registro de usuario.
  • Leer (Read) — visualización del perfil del usuario por otros usuarios del sitio o en la interfaz administrativa.
  • Actualizar (Update) — actualización de datos personales, cambio de correo electrónico o contraseña.
  • Eliminar (Delete) — eliminación de datos.

Al igual, se pueden describir acciones sobre cualquier otro recurso: fotos del usuario, sus amigos, mensajes, etc. Para crear un CRUD completo, debes realizar las siguientes acciones:

  • Crear una entidad en el código (generalmente, es una clase).
  • Agregar una tabla en la base de datos.
  • Escribir pruebas para verificar los manejadores.
  • Agregar manejadores.
  • Agregar plantillas.

A continuación, repasaremos todo el proceso de creación de un CRUD de usuario, a excepción del trabajo con la base de datos y las pruebas.

Comenzaremos con el enrutamiento. Un CRUD completo de usuario incluye al menos siete rutas. Podría haber más, ya que cualquier acción puede repetirse más de una vez:

Método Ruta Plantilla Descripción
GET /users users/index.pug Lista de usuarios
GET /users/new users/new.pug Formulario para crear un nuevo usuario
GET /users/:id users/show.pug Perfil de usuario
POST /users Creación de un nuevo usuario
GET /users/:id/edit users/edit.pug Formulario para editar un usuario
PATCH/PUT /users/:id Actualización de un usuario
DELETE /users/:id Eliminación de un usuario

Esta convención de nomenclatura de rutas apareció originalmente en el marco de trabajo Ruby On Rails, luego fue adaptada por muchos otros. Aquí lo usamos debido a su universalidad y claridad.

Vamos a desglosar las rutas principales y ejemplos de manejadores. Aquí está el código

import fastify from 'fastify';
import view from '@fastify/view';
import pug from 'pug';

const state = {
  users: [
    {
      id: 1,
      name: 'First User',
      email: 'first@user.com,
    },
    {
      id: 2,
      name: 'Second User',
      email: 'second@user.com,
    },
  ],
};

const app = fastify();
const port = 3000;

await app.register(view, { engine: { pug }, root: 'src/views' });

// Vista de la lista de usuarios
app.get('/users', (req, res) => {
  const data = {
    users: state.users,
  };

  res.view('users/index.pug', data);
});

// Formulario para crear un nuevo usuario
app.get('/users/new', (req, res) => res.view('users/new.pug');

// Vista de un usuario específico
app.get('/users/:id', (req, res) => {
  const { id } = req.params;
  const user = state.users.find((item) => item.id === parseInt(id));
  if (!user) {
    res.code(404).send({ message: 'User not found' });
  } else {
    res.view('users/show.pug', { user });
  }
});

// Creación de un usuario
app.post('/users', (req, res) => {
  const user = {
    name: req.body.name,
    email: req.body.email,
    password: req.body.password,
  };

  state.users.push(user);

  res.redirect('/users');
});

// Formulario para editar un usuario
app.get('/users/:id/edit', (req, res) => {
  const { id } = req.params;
  const user = state.users.find((item) => item.id === parseInt(id));
  if (!user) {
    res.code(404).send({ message: 'User not found' });
  } else {
    res.view('users/edit.pug', { user });
  }
});

// Actualización de un usuario
app.patch('/users/:id', (req, res) => {
  const { id } = req.params;
  const { name, email, password, passwordConfirmation, } = req.body;
  const userIndex = state.users.findIndex((item) => item.id === parseInt(id));
  if (userIndex === -1) {
    res.code(404).send({ message: 'User not found' });
  } else {
    state.users[userIndex] = { ...state.users[userIndex], name, email };
    res.send(users[userIndex]);
    res.redirect('/users');
  }
});

// Eliminación de un usuario
app.delete('/users/:id', (req, res) => {
  const { id } = req.params;
  const userIndex = state.users.findIndex((item) => item.id === parseInt(id));
  if (userIndex === -1) {
    res.code(404).send({ message: 'User not found' });
  } else {
    state.users.splice(userIndex, 1);
    res.redirect('/users');
  }
});

app.listen({ port }, () => {
  console.log(`Example app listening on port ${port}`);
});

Create - Crear

  • Creación de un nuevo usuario

Esta acción se realiza mediante solicitudes POST. Son precisamente estas rutas las que procesan los datos de los formularios.

En el ejemplo anterior, obtenemos los datos y los guardamos. Aquí podrían haber controles adicionales para verificar la exactitud de los datos. Normalmente, los datos se guardan en una base de datos, pero aquí los guardamos en un array. Más tarde aprenderemos cómo trabajar con bases de datos.

Read - Leer

  • Vista del perfil del usuario por otros usuarios del sitio
  • Vista del usuario en la interfaz administrativa

Esta acción se lleva a cabo mediante solicitudes GET. En nuestro ejemplo, estas son dos rutas:

  • GET /users: visualización de la lista de usuarios. En el ejemplo, devolvemos el array users().
  • GET /users:id: vista de un usuario específico. En el ejemplo, buscamos al usuario por el id y lo devolvemos. Si no se encuentra al usuario, se devuelve el código 404.

Update - Actualizar

  • Actualización de datos personales.
  • Cambio de correo electrónico.
  • Cambio de contraseña.

Aquí se utilizan los verbos PUT y PATCH, ambos se utilizan para actualizar datos

  • PUT generalmente se usa para actualizar todo el objeto.
  • PATCH se usa cuando solo necesitamos actualizar algunas partes de los datos del objeto.

En Fastify, se define un método para cada uno de estos verbos.

En nuestro ejemplo, obtenemos los datos del formulario req.body, luego buscamos al usuario requerido por el id. Si no se encuentra al usuario, devolvemos el código 404. Si encontramos al usuario, actualizamos los datos de este usuario. Ten en cuenta que no todos los datos pueden actualizarse, por lo que en el ejemplo se utiliza el operador rest { ...users[userIndex] }. En el manejador de esta solicitud, puede haber controles adicionales para verificar la exactitud de los datos.

Delete - Eliminar

Para eliminar, se utiliza el verbo DELETE, en Fastify se define un método similar para él.

En nuestro ejemplo, como en otros manejadores, verificamos la existencia del usuario y eliminamos al usuario si existe. Si no hay usuario, devolvemos el estado 404.

Puedes describir de la misma manera las acciones sobre cualquier otro recurso, las fotos de usuario, sus amigos, mensajes, etc.

Arquitectura de la aplicación

Las operaciones CRUD agrupan las rutas y sus manejadores en bloques lógicos alrededor de algunas entidades. Por ejemplo, el CRUD de cursos, ejercicios, lecciones, artículos de blog, etc. Esta estructura permite dividir la aplicación en archivos, de tal manera que, a medida que la aplicación crece, sea fácil de mantener.

En el desarrollo de Fastify, se acostumbra a agrupar las rutas y manejadores en archivos separados, cada uno relacionado con una entidad específica, y ubicar estos archivos en la carpeta routes:

.
└── routes
    ├── users.js
    ├── posts.js
    └── root.js

En el ejemplo anterior, cada una de las rutas contiene lógica relacionada con una entidad específica:

  • users.js — rutas para usuarios.
  • posts.js — para publicaciones.
  • root.js — rutas que no se relacionan con entidades. Por ejemplo, esta podría ser la ruta de la página principal.

Trabajo independiente

  1. Realiza los pasos del tutorial en tu propia computadora.
  2. Haz que las rutas coincidan con la tabla en la lección.
  3. Separa los controladores en archivos individuales y ajusta el enrutamiento.
  4. Haz lo mismo para la entidad de cursos.
  5. Sube los cambios a GitHub.

Para acceder completo a curso necesitas un plan básico

El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.

Obtener acceso
130
cursos
1000
ejercicios
2000+
horas de teoría
3200
test

Obtén acceso

Cursos de programación para principiantes y desarrolladores experimentados. Comienza tu aprendizaje de forma gratuita

  • 130 cursos, 2000+ horas de teoría
  • 1000 ejercicios prácticos en el navegador
  • 360 000 estudiantes
Al enviar el formulario, aceptas el «Política de privacidad» y los términos de la «Oferta», y también aceptas los «Términos y condiciones de uso»

Nuestros graduados trabajan en empresas como:

Bookmate
Health Samurai
Dualboot
ABBYY