'How to pass foreign key in Golang gin gracefully
It's werid our project's foreign key is name, not id, I am very new to Golang, I have a problem to change our api of POST, When I would like to POST a user with url of http://127.0.0.1:8080/project/3/user
by this json, { "project": "project3", "password": "alice", "username": "alice" }
parameter of project is required, and if I type wrong project name, I will get below error:
"error": "Error 1452: Cannot add or update a child row: a foreign key constraint fails (`test_project`.`users`, CONSTRAINT `project_ibfk_1` FOREIGN KEY (`project`) REFERENCES `projects` (`name`) ON DELETE RESTRICT ON UPDATE CASCADE)"
In my experience, parameter of project is no need, because url http://127.0.0.1:8080/project/3/user already contain project ID, we don't need to post project name, but according to current table and code, I don't know how to change this. Thanks so much for any advice.
And below is user.go
package projects
import (
"test_project/pkg/query"
"time"
)
type User struct {
Id string `gorm:"index:,unique" json:"id"`
Project string `json:"project" binding:"required"`
Username string `json:"username" binding:"required"`
Password string `json:"password"`
CreatedTime time.Time `json:"created_time"`
UpdatedTime time.Time `json:"updated_time"`
}
type UserRepository interface {
Create(User) error
Update(User) error
RetrieveById(id string) (User, error)
RetrieveByName(project string, name string) (User, error)
RetrieveAll(name string, q query.RetrieveBody) (query.RetrieveRes, error)
Delete(id string) error
}
Below is user_service.go
package projects
import (
"test_project/auth"
"test_project/pkg/query"
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type UsersService interface {
Register(context *gin.Context)
}
func (svc projectService) Register(context *gin.Context) {
project_id := context.Param("project_id")
var user User
if err := context.ShouldBindJSON(&user); err != nil {
context.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// generate a uuid
id, err := uuid.NewRandom()
if err != nil {
context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "failed to generate uuid"})
return
}
user.Id = id.String()
// create a user
if err := svc.users.Create(user); err != nil {
context.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
context.Status(http.StatusCreated)
}
And Below is route.go
package router
import (
"test_project/projects"
"test_project/pkg/security"
"github.com/gin-gonic/gin"
)
func MyRouter(svc projects.Service) *gin.Engine {
s := security.New(client)
router := gin.New()
router.Use(logger.GinLogger(), logger.GinRecovery(true))
users := router.Group("projects/:project_id")
{
users.POST("users", s.WriteAccess("project_id"), svc.Register)
users.GET("users", s.ReadAccess("project_id"), svc.ListUsers)
}
return router
}
Below is my two tables
CREATE TABLE IF NOT EXISTS projects(
id CHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
status INT DEFAULT 0,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
CREATE TABLE IF NOT EXISTS users(
id CHAR(36) PRIMARY KEY,
project VARCHAR(255) NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT project_user UNIQUE (project, username),
FOREIGN KEY (project) REFERENCES projects(name) ON DELETE RESTRICT ON UPDATE CASCADE
);
And below is the data of users
select * from users;
---------------------------------------------------------
1 project1 amy project1 2022-03-23 10:04:03 2022-03-25 10:26:07
2 project2 mike project2 2022-03-22 16:43:44 2022-03-25 10:25:29
3 project3 anna project3 2022-03-23 09:26:14 2022-03-25 10:26:23
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
