[GO] Implémentation de l'API pour basculer les valeurs de deux manières (aller)

Choses à faire

Le but est de s'entraîner à devenir le framework Web de Go, Echo. Même si vous basculez la valeur, je pense qu'il y a des cas où la valeur booléenne de la base de données est définie sur true <=> false, et il y a des cas où des enregistrements dans la base de données sont insérés ou supprimés (comme la création d'une fonction favorite à l'aide d'une table intermédiaire). .. Cette fois, après avoir implémenté le premier en tant que modèle BoolToggler, nous implémenterons le second en ajoutant une fonction favorite pour BoolToggler au modèle User. (C'est une application surréaliste et peu pratique, mais c'est une pratique donc je m'en fiche ...) J'ai mis tout le code sur GitHub.

API pour basculer la valeur booléenne de DB

models

C'est le sujet principal 1 de cet article. Basculez True <=> False pour une valeur de colonne de type bool dans le modèle. J'ai défini un tel modèle et j'ai migré.

models/bool_toggler.go

package models

import (
    "github.com/jinzhu/gorm"
)

type BoolToggler struct {
	// type gorm.Model struct {
			// ID        uint           `gorm:"primaryKey"`
			// CreatedAt time.Time
			// UpdatedAt time.Time
			// DeletedAt gorm.DeletedAt `gorm:"index"`
	// }
  gorm.Model
  Toggler bool `json:"toggler"`
}

C'est une structure avec une valeur booléenne simple appelée Toggler. Implémentez la partie api.

Implémentation de l'API

web/api/toggle_bool_toggler.go

package api

import (
	"github.com/labstack/echo"
	"github.com/valyala/fasthttp"
	"strconv"
	"hello/models"
	"hello/middlewares"
)

func ToggleBoolToggler() echo.HandlerFunc {
	return func(c echo.Context) error {
        //Intergiciel de connexion DB
		dbs := c.Get("dbs").(*middlewares.DatabaseClient)
		//Puisque le paramètre de chemin est une chaîne, convertissez-le en uint
		intId, _ := strconv.Atoi(c.Param("id"))
		uintId := uint(intId)

		boolToggler := models.BoolToggler{}
		if dbs.DB.First(&boolToggler, uintId).RecordNotFound() {
			//Si l'ID n'est pas spécifié correctement, le code d'état 404 est renvoyé.
			return c.JSON(fasthttp.StatusNotFound, "Le boolToggler avec l'ID spécifié est introuvable.")
		} else {
			//Inverser la valeur booléenne et enregistrer
			boolToggler.Toggler = !boolToggler.Toggler
			dbs.DB.Save(&boolToggler)
			return c.JSON(fasthttp.StatusOK, boolToggler)
		}
	}
}

Endpoint qui renvoie le Toggler actuellement configuré

web/api/get_bool_toggler.go

package api

import (
	"github.com/labstack/echo"
	"github.com/valyala/fasthttp"
	"hello/models"
	"hello/middlewares"
	"strconv"
)

func GetBoolToggler() echo.HandlerFunc {
	return func(c echo.Context) error {
		dbs := c.Get("dbs").(*middlewares.DatabaseClient)
		intId, _ := strconv.Atoi(c.Param("id"))
		uintId := uint(intId)

		boolToggler := models.BoolToggler{}
		if dbs.DB.First(&boolToggler, uintId).RecordNotFound() {
			return c.JSON(fasthttp.StatusNotFound, "Le boolToggler avec l'ID spécifié est introuvable.")
		} else {
			return c.JSON(fasthttp.StatusOK, boolToggler.Toggler)
		}
	}
}

C'est fondamentalement le même qu'avant. Au lieu de mettre à jour les données, je récupère simplement les valeurs booléennes et les mets dans la réponse.

routes/api.go

func Init(e *echo.Echo) {
	g := e.Group("/api")
    {
        g.PUT("/bool_toggler/:id/toggle", api.ToggleBoolToggler())
        g.GET("/bool_toggler/:id", api.GetBoolToggler()) 
    }
}

Testons l'opération jusqu'à présent.

curl http://localhost:8080/api/bool_toggler/1
>> false

curl -XPUT http://localhost:8080/api/bool_toggler/1/toggle
>> {"ID":1,"CreatedAt":"2020-10-05T14:54:27Z","UpdatedAt":"2020-10-07T10:49:12.1435735Z","DeletedAt":null,"toggler":true}

curl http://localhost:8080/api/bool_toggler/1
>> true

//Données non enregistrées
curl http://localhost:8080/api/bool_toggler/3
>> "Le boolToggler avec l'ID spécifié est introuvable.

J'ai pu confirmer que cela fonctionnait bien.

API pour basculer l'état favori

models

Nous implémenterons une API qui supprime et insère des valeurs dans les données qui expriment la relation dans la table intermédiaire.

Nous allons commencer par créer un modèle utilisateur simple. Puisque le but est d'implémenter des données relationnelles plusieurs-à-plusieurs comme une simple application avec une table intermédiaire, nous ne créons pas de fonction d'authentification. Quoi qu'il en soit, c'est un modèle avec seulement un horodatage et un nom. Migrez de la même manière.

Pour créer une base de données plusieurs-à-plusieurs avec GORM, https://gorm.io/ja_JP/docs/many_to_many.html

models/user.go

package models

import (
  "github.com/jinzhu/gorm"
)

type User struct {
	gorm.Model
	name string `json:"name"`
	//Booléen avec le nom Favorites_Magasin toggler
	Favorites []*BoolToggler `gorm:"many2many:user_favorite_togglers;"`
}

Implémentation d'API

Conception d'URI d'abord, mais parce qu'il n'y a pas de fonction d'authentification

/api/favorite/users/:user_id/bool_togglers/:toggler_id

Vous pouvez voir qu'il est nécessaire de faire référence à chaque entité à partir de plusieurs paramètres de chemin avec l'URI. Ce qui suit est la partie API, mais comme c'est devenu assez compliqué, j'ai laissé beaucoup de commentaires

web/api/toggle_favorite_bool_toggler.go

package api

import (
	"github.com/labstack/echo"
	"github.com/valyala/fasthttp"
	"strconv"
	"hello/models"
	"hello/middlewares"
)

func ToggleFavoriteToggler() echo.HandlerFunc {
	return func(c echo.Context) error {

		//Structure qui crée JSON pour la réponse
		type Response struct {
			UserId         uint
			BoolTogglerId  uint
			Favorite       bool
		}

		//Connexion DB
		dbs := c.Get("dbs").(*middlewares.DatabaseClient)
		
		//Convertir les paramètres de chemin en uint
		intUserId, _ := strconv.Atoi(c.Param("user_id"))
		uintUserId := uint(intUserId)
		intTogglerId, _ := strconv.Atoi(c.Param("toggler_id"))
		uintTogglerId := uint(intTogglerId)

		//Instancier la structure de réponse
		var resJSON Response
		resJSON.UserId = uintUserId
		resJSON.BoolTogglerId = uintTogglerId

		//Passez le boolToggler avec l'ID spécifié lors de l'ajout
		var boolToggler models.BoolToggler
		boolToggler.ID = uintTogglerId
		
		//Activez les relations utilisateurs dans Preload et sélectionnez
		user := &models.User{}
		dbs.DB.Preload("Favorites", "bool_toggler_id = ?", uintTogglerId).
		Find(&user, uintUserId)

		//Ajouter un nouvel enregistrement s'il n'a pas encore été ajouté aux favoris
		if len(user.Favorites) < 1 {
			dbs.DB.Model(&user).Association("Favorites").Append(&boolToggler)
			resJSON.Favorite = true

		//Supprimer l'enregistrement existant s'il a été ajouté aux favoris
		} else {
			dbs.DB.Model(&user).Association("Favorites").Delete(&boolToggler)
			resJSON.Favorite = false
		}
		return c.JSON(fasthttp.StatusOK, resJSON)
	}
}

routes/api.go

g.POST("/favorite/users/:user_id/bool_togglers/:toggler_id", api.ToggleFavoriteToggler()) //Postscript

Quand j'essaye curl, la valeur est basculée correctement.

curl -XPOST http://localhost:8080/api/favorite/users/1/bool_togglers/1
{"UserId":1,"BoolTogglerId":1,"Favorite":false}
/go/src/app # curl -XPOST http://localhost:8080/api/favorite/users/1/bool_togglers/1
{"UserId":1,"BoolTogglerId":1,"Favorite":true}

De plus, lorsque j'ai vérifié la table mysql, j'ai pu confirmer le comportement prévu.

mysql> select * from user_favorite_togglers;
+---------+-----------------+
| user_id | bool_toggler_id |
+---------+-----------------+
|       1 |               1 |
+---------+-----------------+
1 row in set (0.00 sec)

//Après l'accès
mysql> select * from user_favorite_togglers;
Empty set (0.00 sec)

Point de terminaison qui renvoie les informations utilisateur

web/api/show_user.go

package api

import (
	"github.com/labstack/echo"
	"github.com/valyala/fasthttp"
	"hello/models"
	"hello/middlewares"
	"strconv"
)

func ShowUserInfo() echo.HandlerFunc {
	return func(c echo.Context) error {

		type ResToggler struct {
			BoolTogglerId uint
			Toggler       bool
		}

		type Response struct {
			UserId uint
			Name   string
			Favorites []ResToggler
		}

		dbs := c.Get("dbs").(*middlewares.DatabaseClient)
		//Convertir les paramètres de chemin en uint
		intUserId, _ := strconv.Atoi(c.Param("id"))
		uintUserId := uint(intUserId)
		
		//Activez les relations utilisateurs dans Preload et sélectionnez
		user := models.User{}
		dbs.DB.Preload("Favorites").Find(&user, uintUserId)

		var resJSON Response
		resJSON.UserId = user.ID
		resJSON.Name   = user.Name
		for _, v := range user.Favorites {
			toggler := ResToggler{
				BoolTogglerId: v.ID,
				Toggler: v.Toggler,
			}
			resJSON.Favorites = append(resJSON.Favorites, toggler)
		}
		return c.JSON(fasthttp.StatusOK, resJSON)
	}
}

La bonne chose à propos du framework Echo est que si vous définissez une structure pour Response, vous pouvez la passer en tant que JSON telle quelle. Le résultat renvoie une structure comme celle-ci:

curl http://localhost:8080/api/user/1
{"UserId":1,"Name":"test_user01","Favorites":[{"BoolTogglerId":1,"Toggler":false}]}

Recommended Posts

Implémentation de l'API pour basculer les valeurs de deux manières (aller)
J'ai essayé deux façons de combiner plusieurs commits avec Git
Deux façons d'afficher plusieurs graphiques dans une seule image avec matplotlib
Une histoire déroutante avec deux façons d'implémenter XGBoost en Python + notes générales
3 façons d'analyser les chaînes de temps avec python [Note]
Implémentation minimale d'Union Find en Python
Deux façons de décoder des tuiles vectorielles binaires en GeoJSON
Exemple de serveur d'API qui reçoit JSON dans Golang
Comment créer une API Rest dans Django