How to get struct name inside custom validation function - validation

this is my struct:
type User struct {
Name `validate:"custom_validation"`
}
this is my custom validation:
func customFunc(fl validator.FieldLevel) bool {
// I want to get struct name inside here
// do some validations...
return true
}
validate.RegisterValidation("custom_validation", customFunc)
the reason is I need to do some check to the database, I need the table name for that, therefore I need the struct name, because the table name is similar to the struct name. If I hard-coded the table name this customFunc cannot be used to validate in other struct.
How can I do that?
ref: https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Custom_Validation_Functions

Simple
Get name of the field:
fl.FieldName()
Get value of the field:
fl.Field().String()
Get struct type:
fl.Parent().Type().String()

Related

How do I use custom preload in gorm

I have these 2 structs
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
gorm.Model
Name string
Adress string
}
I want to get users and preload their companies but I don't want to get the Adress field I tried the custom preload like bellow and I tested it in postman . the query returned all the fields but for adress I get an empty string , the reason why this is happening is that when storing the result in the user struct golang automatically initialize all the fields and the field adress get returned with its initial value which is an empty sting
var user []User
db.Table("users").Preload("Company",func(db *gorm.DB) *gorm.DB {
return db.Select("ID" ,"Name")
}).Find(&user)
what should I do to only have the name and id but not the adress
If your server exports the result as json you could add the json tag omitempty as such:
type Company struct {
gorm.Model
Name string
Adress string `json:"omitempty"`
}
That way the address field will not be included if it is an empty string.

GORM AutoMigrate Has One & Has Many:

I want to create a model User and Social where the User model has many Socials. Ideally a Social type would also have has one relation to simpilify querying from either side. Here is a code sample:
database type is MySQL 8.0
type base struct {
ID string `json:"id" gorm:"type:char(36);primaryKey;"`
Created time.Time `json:"created" gorm:"autoCreateTime"`
Updated time.Time `json:"updated" gorm:"autoUpdateTime"`
}
type User struct {
base
Friends []*User `json:"friends" gorm:"many2many:friends"`
Socials []*Social `json:"socials"`
}
type Social struct {
base
Provider string `json:"provider" gorm:"type:varchar(32);index"`
Identifier string `json:"identifier" gorm:"type:varchar(32);index"`
User *User `json:"user" gorm:"foreignKey:ID"`
Token string `json:"token"`
Link string `json:"link" gorm:"type:varchar(128)"`
}
Im getting the following error when using db.AutoMigrate(&User{}, &Social{}):
model.Social's field User, need to define a valid foreign key for relations or it need to implement the Valuer/Scanner interface
runtime error: invalid memory address or nil pointer dereference
I have tried:
adding gorm:"foreignKey:ID" to User.Socials tags
not using pointers (eg in User struct Socials []Social instead of Socials []*Social)
but the issue remains
According to documentation (https://gorm.io/docs/has_many.html#Has-Many),
you need to use objects, not references
type User struct {
base
Friends []User `json:"friends" gorm:"many2many:friends"`
Socials []Social `json:"socials"`
}
no * here
Also you can add UserID field to Social
type Social struct {
base
UserID string
Provider string `json:"provider" gorm:"type:varchar(32);index"`
Identifier string `json:"identifier" gorm:"type:varchar(32);index"`
User *User `json:"user" gorm:"foreignKey:ID"`
Token string `json:"token"`
Link string `json:"link" gorm:"type:varchar(128)"`
}
and add
type User struct {
base
FriendOf string `gorm:""`
Friends []*User `json:"friends" gorm:"many2many:friends,foreignKey:FriendOf"`
Socials []*Social `json:"socials"`
}
Issue was here:
type base struct {
...
}
type User {
base
...
}
type Social {
base
...
}
Since I thought base would just be package local definition I messed up the capitalization and had a private primary key.
Another issue was touched on by #vodolaz095, but (imo) not sufficiently clarified for any new go-gorm user.
It does not seem to be possible to use a has one relation like User User be the foreign key for a has many relation like Socials []Social gorm:"foreignKey:User". It is required to be split up as #vodolaz095 displayed in his 2nd code block

Defining Belongs To relation for anonymous field using GORM

I wanted to create relationnal database structure in a using the go package Gorm.
I wanted to add foreign keys to my structure, it works perfectly on regular field, but it does not seem to work when I want to make foreign key for anonymous fields.
Here is some simplified code to demonstrate my case
type StructA struct {
gorm.Model
SimpleFieldID int // appears in database as foreign key
SimpleField StructB
TranslationID int // appears in database as a regular int
Translation
}
type StructB struct {
gorm.Model
SomeField string
SomeOtherField string
}
type Translation struct {
gorm.Model
En string
Fr string
}
I wanted to have anonymous field in the first place to be able to call some GetName() method on any object that has the Translation attribute.
I found this question, but the given anwser was for the has-one relation, where I want to use a belongs-to relation.

One model for POST and GET with different "required" field

I use go-swagger. I have model like:
// Pet pet
// swagger:model
type Pet struct {
// id
ID int64 `json:"id,omitempty"`
// name
// Required: true
Name *string `json:"name"`
}
and for example in my POST field Name have to be required but for GET not. So how should I add it if I don't want create similar model without required? Because for now my only thought is to create type PetGET struct and type PetPOST struct which, I guess is stupid idea.
If you're generating spec from code, then having a PetGET and PetPOST is not a stupid idea. Usually the program model doesn't match the API model, and you have to repeat definitions just to generate the spec right. So you have a couple of options here:
You can simply mark the field required: false, and deal with it in the GET handler.
If you're generating spec from code, you can create swagger-only models separate from your program models, and for cases like this, create two models with different annotations.

Trouble defining inter-table relationship

Goal
I am trying to setup a simple has_many association with Gorm: a person has many pets.
Problem
I see the following error when I try to save the Person model.
unsupported type []model.Pet, a slice of struct
Details
Assume I want to save an Person that has many Pets.
type Person struct {
UUID `gorm:"PRIMARY_KEY" json:"uuid"`
Pet []Pet `gorm:"foreignkey:PersonUUID:association_foreignkey:UUID"`
}
type Pet struct {
UUID `gorm:"PRIMARY_KEY" json:"uuid"`
PersonUUID string
}
Then I try to create these two models.
personUUID := "dcf4b3c6-d94c-4b2c-9d66-1cbaedd2cc44"
pets := []Pet{
Pet{
UUID: "..",
PersonUUID: personUUID,
}
}
person := Person{
UUID: personUUID,
Pet: Pet,
}
db.Where("uuid = ?", person.UUID).Update(&person)
Then I get the following error.
sql: converting argument $1 type: unsupported type []model.Pet, a slice of struct
Any idea why this might be happening?
I found out it only happens if you use Update instead of Save.
This is odd, because both should work the same way except that Update will try to save the different fields while Save will replace the current values with the new values.

Resources