Newbie here. I have this gqlgen api with sqlc update code, which updates the user by given id with provided fields:
// graph/schema.resolvers.go
...
func (r *mutationResolver) UserUpdate(ctx context.Context, id string, input model.EditUser) (bool, error) {
// Validate
v := validator.New()
if err := v.Struct(input); err != nil {
for _, err := range err.(validator.ValidationErrors) {
fmt.Println(err)
}
return false, errors.New(err.Error())
}
pg := db.ConnectPg()
defer pg.Close()
// Parse string id to int64
parsedId, _ := strconv.ParseInt(id, 10, 64)
u := db.User{}
var err error
// GetUserById is generated by sqlc
if u, err = db.NewPg(pg).GetUserById(ctx, parsedId); err != nil {
return false, err
}
// Confirm ownership or admin
user := auth.ForContext(ctx)
if user != nil || user.ID == parsedId || user.IsAdmin {
if input.EmailVerified != nil {
u.EmailVerified = *input.EmailVerified
}
if input.MobileVerified != nil {
u.MobileVerified = *input.MobileVerified
}
if input.IsActive != nil {
u.IsActive = *input.IsActive
}
if input.Name != nil {
u.Name = sql.NullString{String: *input.Name, Valid: true}
}
if input.Avatar != nil {
u.Name = sql.NullString{String: *input.Avatar, Valid: true}
}
if input.Email != nil {
u.Email = sql.NullString{String: *input.Email, Valid: true}
}
if input.Mobile != nil {
u.Mobile = sql.NullString{String: *input.Mobile, Valid: true}
}
if input.Password != nil {
bytes, _ := bcrypt.GenerateFromPassword([]byte(*input.Password), 14)
hashedPassword := string(bytes)
u.Password = hashedPassword
}
if input.IsAdmin != nil {
if user.IsAdmin {
u.IsAdmin = *input.IsAdmin
} else {
return false, fmt.Errorf("Access denied")
}
}
// UpdateUser and UpdateUserParams are generated by sqlc
if _, err := db.NewPg(pg).UpdateUser(ctx, db.UpdateUserParams{
ID: u.ID,
Name: u.Name,
Avatar: u.Avatar,
Email: u.Email,
EmailVerified: u.EmailVerified,
Mobile: u.Mobile,
MobileVerified: u.MobileVerified,
Password: u.Password,
IsAdmin: u.IsAdmin,
IsActive: u.IsActive,
UpdatedAt: time.Now(),
}); err != nil {
return false, err
}
return true, nil
}
return false, fmt.Errorf("Access denied")
}
...
And it is working correctly. However coming from Node land, I feel like it is too verbose. Or is this just how Golang does it? What if I have like more than 10 columns, do I have to check nil for each of them?
I tried searching some Golang tutorials but couldn't find much out there like Node. How would an experienced Gopher write this code in neat?
Other information you may need.
This is EditUser struct "generated" by gqlgen but can be edited:
// graph/models/user.go
type EditUser struct {
Name *string `json:"name,omitempty" validate:"omitempty,max=100"`
Avatar *string `json:"avatar,omitempty"`
Email *string `json:"email,omitempty" validate:"omitempty,email"`
EmailVerified *bool `json:"emailVerified,omitempty"`
Mobile *string `json:"mobile,omitempty" validate:"omitempty,min=2,max=55"`
MobileVerified *bool `json:"mobileVerified,omitempty"`
Password *string `json:"password,omitempty"`
IsAdmin *bool `json:"is_admin,omitempty"`
IsActive *bool `json:"isActive,omitempty"`
}
This is User struct "generated" by sqlc:
// db/models.go
// Code generated by sqlc. DO NOT EDIT.
package db
type User struct {
ID int64 `json:"id"`
Name sql.NullString `json:"name"`
Avatar sql.NullString `json:"avatar"`
Email sql.NullString `json:"email"`
EmailVerified bool `json:"email_verified"`
Mobile sql.NullString `json:"mobile"`
MobileVerified bool `json:"mobile_verified"`
// is required
Password string `json:"password"`
IsAdmin bool `json:"is_admin"`
IsActive bool `json:"is_active"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastSignin sql.NullTime `json:"last_signin"`
}
This is UpdateUserParams "genearted" by sqlc:
// db/user.sql.go
// Code generated by sqlc. DO NOT EDIT.
// source: user.sql
type UpdateUserParams struct {
ID int64 `json:"id"`
Name sql.NullString `json:"name"`
Avatar sql.NullString `json:"avatar"`
Email sql.NullString `json:"email"`
EmailVerified bool `json:"email_verified"`
Mobile sql.NullString `json:"mobile"`
MobileVerified bool `json:"mobile_verified"`
Password string `json:"password"`
IsAdmin bool `json:"is_admin"`
IsActive bool `json:"is_active"`
UpdatedAt time.Time `json:"updated_at"`
}
go (v1.15), sqlc (v1.5.0), gqlgen (v0.13.0)
if input.Avatar != nil { u.Name = sql.NullString{…I hope you have unit tests in place. And yes, this is not the way to code this, me not knowing how to in Go notwithstanding. \$\endgroup\$