I am using the GORM ORM library for Golang to model the above relation. Here is the model code for the same:
package models
import (
"errors"
"fmt"
"regexp"
"gorm.io/gorm"
)
type User struct {
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
FirstName string `gorm:"column:first_name" json:"first_name"`
LastName string `gorm:"column:last_name" json:"last_name"`
Email string `gorm:"column:email" json:"email"`
Bio string `gorm:"column:bio" json:"bio"`
Blogs []Blog `gorm:"foreignKey:author_id"`
BlogReactions []BlogReaction `gorm:"foreignKey:user_id"`
CommentReactions []CommentReaction `gorm:"foreignKey:user_id"`
Comments []Comment `gorm:"foreignKey:user_id"`
Followers []User `gorm:"many2many:has_followers"`
}
func (*User) TableName() string {
return "user"
}
func (u *User) validate() (err error) {
fmt.Println(u)
if u.FirstName == "" {
return errors.New("first name cannot be empty")
}
emailMatched, _ := regexp.MatchString("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$", u.Email)
if !emailMatched {
return errors.New("invalid email format")
}
if len(u.Bio) > 200 {
return errors.New("bio too long")
}
return
}
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
validationErr := u.validate()
return validationErr
}
I have a validation check before save. When I try to append a new follower:
dbErr := database.DB.
Model(&models.User{ID: uint(id)}).
Association("Followers").
Append(&models.User{ID: uint(follower_id)})
I get the validation error since the object has no information other than the ID:
first name cannot be empty
If the primary key is present in the object fed into Model() shouldn't the other fields auto populate? How can I resolve this?
I solved it, the solution was to create 2 User instances and populate them with the user
and follower
data using the First
. Here's the complete endpoint function:
func AddFollower(w http.ResponseWriter, r *http.Request) {
id, parseIDErr := strconv.ParseUint(mux.Vars(r)["id"], 10, 64)
follower_id, parseFollowerIDErr := strconv.ParseUint(mux.Vars(r)["follower_id"], 10, 64)
//These 2 instances must be fully populated before the append operation
var user models.User
var follower models.User
if parseIDErr != nil || parseFollowerIDErr != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
tx := database.DB.Begin()
//Find the user
if err := tx.First(&user, id).Error; err != nil {
utilities.HandleDBError(err, r.URL.String(), w, "user")
return
}
// Find the follower
if err := tx.First(&follower, follower_id).Error; err != nil {
utilities.HandleDBError(err, r.URL.String(), w, "user")
return
}
// Here the validation shouldn't fire since all fields are populated
if err := tx.
Model(&user).
Association("Followers").
Append(&follower); err != nil {
tx.Rollback()
utilities.HandleDBError(err, r.URL.String(), w, "user")
return
}
if err := tx.Commit().Error; err != nil {
utilities.HandleDBError(err, r.URL.String(), w, "user")
return
}
w.WriteHeader(http.StatusCreated)
}