I am new to golang and gorm.io and so might have made some basic mistakes.
I am trying to add the ability to save tags to the repositories in my project but I am struggling to understand if this is something that gorm can help with and how I would do it with gorm.
Current Environment
go version go1.17.2 darwin/amd64
gorm.io/driver/postgres v1.0.8
gorm.io/gorm v1.21.8
I have the following scenario.
Data Structure: User -> Belongs_to One - Organisation -> Has_Many Repositories -> Has_Many Tags
My Structs
type Organization struct {
gorm.Model
UserID uuid.UUID
OrgName string
Repositories []Repository
}
type Repository struct {
gorm.Model
Name string `gorm:"index"`
Version string
Description string
URL string
OrganizationID uuid.UUID
Tags []*Tag `gorm:"many2many:repository_tags;"`
}
type Tags struct {
gorm.Model
Name string
Repositories []*Repository `gorm:"many2many:repository_tags;"`
}
type Tag struct {
database.DefaultModel
Name string
Repositories []*Repository `gorm:"many2many:repository_tags;"`
}
Workflow:
- User registers themselves on a site.
- During the user creation a personal organisation is created with the username.
- User is assigned to the organisation.
- User Creates repositories in their organisation.
Each Repository could have one or many tags. Tags can be common across organisations.
Questions
- Is my struct design correct for such a multi tier data structure?
- When I call the function below the repository record is created but the tags are not.
- Is there a better way to do this?
//Create a new repository
func NewRepository(c *fiber.Ctx) error {
c.Accepts("application/json")
// Valid Header
if !helpers.ValidRequestHeader(c) {
return apperr.UnsupportedMediaType("Not Valid Content Type, Expect application/json")
}
var id uuid.UUID
orgname := strings.ToLower(c.Params("org"))
user_token := c.Locals("user").(*jwt.Token)
claims := user_token.Claims.(jwt.MapClaims)
username := claims["username"].(string)
db := database.DB
id = helpers.GetUserIDByUserName(username)
var organization models.Organization
repository := new(models.Repository)
// Check for a valid token
if !helpers.ValidToken(user_token, id) {
return c.Status(500).JSON(fiber.Map{"Status": "Error", "Message": "Invalid token id", "Data": nil})
}
// find the org in the organization table
db.Where("org_name = ?", orgname).Find(&organization)
if username != orgname {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"Status": "Error", "Message": "Unauthorized", "Data": nil})
}
if username == orgname {
db.Model(&organization).Where("org_name = ?", orgname).Association("Repositories").Append(repository)
}
return c.JSON(repository)
}
if I use this JSON calling the create function.
{
"name": "applicationrepo",
"user": "superman",
"version": "0.2.2",
"description": "Repository",
"url": "https://github.com/repoorg/repo",
"tags": [
{"name": "Golang"},
{"name": "DBBackend"}
]
}
I get this returned
{
"id": "0204f336-a622-46c4-9abb-3de08208c237",
"name": "applicationrepo",
"version": "0.2.2",
"description": "Repository",
"url": "https://github.com/repoorg/repo",
"orgid": "fd94183c-e553-423e-a38f-fcecc4540bca",
"tags": [
{
"id": "00000000-0000-0000-0000-000000000000",
"Name": "Golang",
"Repositories": null
},
{
"id": "00000000-0000-0000-0000-000000000000",
"Name": "DBBackend",
"Repositories": null
}
]
}
and the tags are not written to the tags table or the join table.
How can I get GORM to do this for me or should I look at some other way to create records in my application?
Thanks in advance.