Aller au contenu principal

28-7 Ajout de l'action create au contrôleur de projets

Nous sommes en mesure de récupérer tous les projets ainsi qu'un seul. Il serait bien maintenant de pouvoir en ajouter de nouveaux.

Pour cela, toujours selon la convention Nest, il est suggéré d'utiliser une fonction create() répondant e à la méthode HTTP POST.

VerbeCheminAction du contrôleur
GET/projetsfindAll()
POST/projetscreate()
GET/projets/:idfindOne()
PUT/PATCH/projets/:idupdate()
DELETE/projets/:idremove()

En entrée, il nous faudra un Projet, mais nous avons un dilemme: pas tous les attributs sont nécessaires afin de créer un nouveau projet. En fait, certains attributs n'auraient pas de sens à recevoir en entrée: id, date_creation et date_modification, par exemple. En effet, on ne crée pas un projet en connaissant à l'avance son id, c'est une valeur retournée par le serveur.

Il nous faut une façon de représenter l'objet tel qu'il sera reçu et attendu pour sa création. Cela permettra aussi de personnaliser les validations.

Cette représentation s'appelle un DTO (Data Transfer Object). Il s'agit d'une classe qui représente un objet dans un état de transfert de données (pour la création ou la modification, par exemple). C'est un objet utilisé seulement pour représenter l'état des données au moment du transfert entre le client et le serveur.

C'est similaire aux objets de requêtes créés dans Angular.

Créer un DTO CreateProjetDto

Les DTO, tout comme les modèles ou les entités, sont des classes simples que l'on place dans le dossier du module concerné.

  1. Créez le dossier dto sous projets: src/projets/dto

  2. Sous ce nouveau dossier, ajoutez un fichier TypeScript create-projet.dto.ts

  3. À l'intérieur de ce nouveau fichier, créez la classe CreateProjetDto avec les attributs pour la création

    src/projets/dto/create-projet.dto.ts
    export class CreateProjetDto {
    nom: string;
    description: string;
    image_url?: string;
    }
    info

    Il est tout de même possible de spécifier des attributs optionnels, comme image_url dans notre cas.

Ajouter la fonction creer() au service ProjetsService

Le service est ultimement responsable de gérer la coordination d'ajout de projet. Pour ce faire, on créera une fonction creer acceptant en paramètre un DTO CreateProjetDto.

Comme nous n'avons pas de base de données encore, on créera le tout de façon manuelle en ajoutant le projet au tableau.

  1. Ajoutez une fonction creer au service ProjetsService

    src/projets/projets.service.ts
    //...

    creer(createProjetDto: CreateProjetDto) {

    }

    //...
  2. Trouvons l'id le plus élevé dans la liste à l'aide de la fonction reduce afin de créer automatiquement un nouvel id pour le nouveau projet.

    src/projets/projets.service.ts
      creer(createProjetDto: CreateProjetDto) {
    const maxId = this.projets.reduce((max, projet) => {
    return Math.max(max, projet.id);
    }, 0);
    }
    info

    La fonction reduce exécute la fonction passée en paramètre pour chaque item de la liste projet et met le retour dans une variable (max ici) réutilisée à chaque itération.

    Pour chaque projet existant dans la liste, on vérifie si son identifiant est plus élevé que celui déjà contenu dans la variable max et si oui, on retourne l'id. Il sera ainsi associé à la variable max et passé à la prochaine itération.

  3. Créer le projet reçu en lui assignant un id et une date de creation/modification.

    src/projets/projets.service.ts
    creer(createProjetDto: CreateProjetDto) {
    const maxId = this.projets.reduce((max, projet) => {
    return Math.max(max, projet.id);
    }, 0);

    const projet: Projet = {
    id: maxId + 1,
    nom: createProjetDto.nom,
    description: createProjetDto.description,
    date_creation: new Date().toJSON(),
    date_modification: new Date().toJSON(),
    };
    //highlight-next
    }
  4. Ajouter le nouveau projet à la liste en mémoire et le retourner

    src/projets/projets.service.ts
    creer(createProjetDto: CreateProjetDto) {
    const maxId = this.projets.reduce((max, projet) => {
    return Math.max(max, projet.id);
    }, 0);

    const projet: Projet = {
    id: maxId + 1,
    nom: createProjetDto.nom,
    description: createProjetDto.description,
    date_creation: new Date().toJSON(),
    date_modification: new Date().toJSON(),
    };

    this.projets.push(projet);
    return projet;
    }

Ajouter l'action create au contrôleur ProjetsController

Il est maintenant temps d'ajouter la fonction create() au contrôleur répondant à la méthode HTTP POST.

  1. Ajouter la fonction create avec le décorateur @Post

    src/projets/projets.controller.ts
    @Post()
    create() {

    }
  2. Récupérer le body de la requête via le décorateur de paramètre @Body()

    src/projets/projets.controller.ts
    @Post()
    create(@Body() createProjetDto: CreateProjetDto) {

    }
    info

    Le décorateur Body permet de récupérer le body de la requête et de l'assigner à un paramètre de la fonction. Il est possible de préciser à quel type d'objet devrait correspondre la requête, soit CreateProjetDto dans notre cas.

  3. Appeler le service via sa fonction creer pour créer le projet et le retourner

    src/projets/projets.controller.ts
    @Post()
    create(@Body() createProjetDto: CreateProjetDto) {
    return this.projetsService.creer(createProjetDto);
    }
info

En résumé:

  • Le contrôleur utilise le décorateur @Post() pour préciser que la fonction create sera responsable des méthodes HTTP POST.
  • Dans la signature de la fonction, on récupère le body de la requête, qui est au fond le JSON reçu et on l'assigne à la variable createProjetDto de type CreateProjetDto.
  • Le projet est retourné

Test Postman

Testez via Postman à l'aide d'une requête:

  • Type: POST
  • URL: http://localhost:3000/projets
  • Body: raw / JSON contenant
    {
    "nom": "Un nouveau projet",
    "description": "Comme si je n'en n'avais pas déjà assez."
    }

Vous devriez recevoir comme un résultat semblable à ceci:

{
"id": 3,
"nom": "Un nouveau projet",
"description": "Comme si je n'en n'avais pas déjà assez.",
"date_creation": "2024-10-11T14:09:54.368Z",
"date_modification": "2024-10-11T14:09:54.368Z"
}