How can we create a similar model field type to Django field.choices in GORM/Golang - go

I am trying to create a struct field, and limit its values to a list of values i.e,
state =["locked", "unlocked"]
now in Django models we use the field choices i.e
class Book(models.Model):
LOCKED = 'LK'
UNLOCKED = 'UN'
STATE = [
('LK', 'Locked'),
('UL', 'Unlocked'),
]
book_state = models.CharField(choices=STATE, default=LOCKED)
trying to replicate the above using a gorm.model struct data type in Go.

Solution: create a custom golang type with string and add it as gorm model field
type BookState string
const (
Locked BookState = "locked"
Unlocked BookState = "unlocked"
)
Then create your gorm struct model fields
type Book struct {
Name string `json:"name" validate:"required"`
State BookState `json:"state" validate: "required"`
....
}

Related

Gorm 2, Golang, Auto migrate table with foreign key

import "gorm.io/gorm"
type Object struct {
gorm.Model
ObjectId string `gorm:"primary_key"`
ListItems []ListItem `gorm:"foreignKey:ObjectId;references:ObjectId"`
}
type ListItem struct {
gorm.Model
ObjectId string
Data string
}
I define two objects, then try to auto migrate following the guide
db.Migrator().CreateConstraint(&Object{}, "ListItems")
db.Migrator().CreateConstraint(&Object{}, "fk_object_list_items")
db.AutoMigrate(&Object{}, &ListItem{})
Fails with
ERROR: there is no unique constraint matching given keys for referenced table "blobber_ch
I can't find any examples for this. I tried different permutations of everything.
I suspect the foreign key in the migration does not match the foreign key in the model.
You have two primary_key for Object struct as gorm.Model already have one:
ID uint `gorm:"primarykey"`
You have two otpions : not to use gorm.Model or get rid of ObjectId primary_key and clean references:ObjectId from gorm annotation.
type Object struct {
gorm.Model
ObjectId string
ListItems []ListItem `gorm:"foreignKey:ObjectId;"`
}
type ListItem struct {
gorm.Model
ObjectId string
Data string
}
db.Migrator().CreateConstraint(&Object{}, "ListItems")
db.Migrator().CreateConstraint(&Object{}, "fk_object_list_items")
db.AutoMigrate(&Object{}, &ListItem{})

Does type definition help assign restricted values?

In the below struct type:
type Employee struct {
Name string `json:"name"`
JobTitle JobTitleType `json:"jobtitle"`
}
member JobTitle should be ensured to have restricted(specific) values( of string type).
type JobTitleType string
const(
GradeATitle JobTitleType = "Clerk"
GradeBTitle JobTitleType = "Manager"
)
Does type definition(JobTitleType) help assign restricted values to member JobTitle?
No. You can assign any value to JobTitle:
e.JobTitle=JobTitleType("bogus")
The JobTitleType is based on string, so all string values can be converted to it.
You can use getter/setters to enforce runtime validation.
No, it will not restrict the values, any value that has type JobTitleType can be assigned to JobTitle. Currently, there is no enum type in Go. For restricting values you will probably need to write your own logic.
No, you should use it in the validation logic. For example, https://github.com/go-playground/validator has oneOf operator for validation.
Go don't have enum type, but you can do something like this
package main
import (
"fmt"
)
var JobTitleTypes = newJobTitleTypeRegistry()
func newJobTitleTypeRegistry() *jobTitleTypeRegistry{
return &jobTitleTypeRegistry{
GradeATitle : "Clerk",
GradeBTitle : "Manager",
}
}
type jobTitleTypeRegistrystruct {
GradeATitle string
GradeBTitle string
}
func main() {
fmt.Println(JobTitleTypes.GradeATitle)
}

Gorm w/ Postgres has a nested struct as JSON

I am using GORM and I want to store the following struct in Postgres:
// Value GoDoc
type Value struct {
Name string
Place string
Value interface{}
}
// SharedConfig stores tenant-wide shared values
type SharedConfig struct {
gorm.Model
TenantID string
ProgramID *string
Name string
Value Value
}
I want to store SharedConfig in my DB and want the Value column to be stored as JSON, is this possible? I've only seen uses of the json column type as postgres.Jsonb

Query with 'has one' association (one-to-one)

I'm playing a bit with Gorm while I'm trying to decide which ORM library fit the most for my needs.
Important to mention that I'm currently working with Sqlite.
Following the guide I created two structs:
type Color struct {
gorm.Model
UserID uint
Name string
}
//User struct define a basic user model
type User struct {
gorm.Model
Username string
Email string
FirstName string
LastName string
Password string
CreationDate time.Time
DOB time.Time
IgnoreMe int `gorm:"-"` // Ignore this field
Color Color `gorm:"foreignkey:ColorRefer"`
ColorRefer uint
}
when I'm creating a DB with
func CreateTables() {
user := dm.User{}
color := dm.Color{}
GormDB.CreateTable(&color)
GormDB.CreateTable(&user)
GormDB.Model(&user).AddForeignKey("ColorRefer", "colors(id)", "CASCADE", "CASCADE")
}
or with:
func CreateTables() {
GormDB.AutoMigrate(&dm.User{},&dm.Color{})
}
Sadly it's not working as I would of expect and create the foreign key automatically, but it's works when I do it manually.
My main problem is when I'm trying to query Users
//QueryByStructExample query users table by the struct non-zero (non-default) fields.
func QueryByStructExample(userStruct dm.User) []dm.User {
var results []dm.User
GormDB.Where(userStruct).Find(&results)
return results
}
I created the following function in a try to query users by email with the color property which is my color struct and I tried to play with a lot with the Model,Related and the Association functions, and nothing seems to work and (I'm avoiding to use join by purpose).
The end result is that it query my User but without the color (only with the ID in my colorRefer)
any suggestion?
Do you mean to preload the Color struct? If yes did you try to query it like that
GormDB.Preload('Color').Where(userStruct).Find(&results)

How can I add a new boolean property to a Golang struct and set the default value to true?

I have a user struct that corresponds to an entity. How can I add a new property active and set the default value to true?
Can I also set the value of that property to true for all existing entities by some easy method?
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
Bonus questions: I don't quite understand the syntax in the struct. What do the three columns represent? What do the JSON strings have ``around them?
//You can't change declared type.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
//Instead you construct a new one embedding existent
type ActiveUser struct {
User
Active bool
}
//you instantiate type literally
user := User{1, "John"}
//and you can provide constructor for your type
func MakeUserActive(u User) ActiveUser {
auser := ActiveUser{u, true}
return auser
}
activeuser := MakeUserActive(user)
You can see it works https://play.golang.org/p/UU7RAn5RVK
You have to set the default value as true at the moment when you are passing the struct type to a variable, but this means you need to extend that struct with a new Active field.
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Active bool
}
user := User{1, "John", true}
json:"id" means that you are mapping the json decoded object field to the field id in your struct type. Practically you are deserialize the json string into object fields which later you can map to their specific field inside the struct.

Resources