GORM Not ignoring field with `gorm:"-"` - go

Using Jinzhu's GORM Package which is fantastic btw, I currently have this struct:
type User struct {
gorm.Model
// The Users username
Username string `gorm:"size:255;unique;not null"`
// The Users email address
Email string `gorm:"size:255;unique;not null"`
// The Users hashed password
Password string `gorm:"size:255;not null"`
// The Users password confirmation (only for forms)
PasswordC string `gorm:"-"`
// The Users FULL NAME (e.g. Burt Reynolds)
Fullname string `gorm:"size:255; not null"`
// The Users Karma level
Karma int
// Is the user banned?
Banned bool
}
But I also use Gorilla's Schema package so any form values populate the struct, but I don't want the PasswordC to be saved into the database because it will be plain text as the normal Password field gets bcrypt'd so any information on how to make GORM not save the PasswordC field.

The docs say gorm:"-", but the code indicates sql:"-" is the correct syntax.
My testing verifies this.

This is no longer correct. The code has been fixed, still use gorm:"-".

Related

How to accept only one of multiple fields in Go Validator?

type CoolName struct {
Foo string `json:"foo"`
Bar string `json:"bar"`
}
With the Go validator, I want to make only one of these two fields required and give an error if the content of both fields is full.
I used required_without but it only helps with requiring one of them. I can't figure out how can i validate if both fields doesn't have a content at the same time.
i have follow this and work for me,
ref : https://github.com/go-playground/validator/issues/617
type Auth struct {
APIKey string `json:"apiKey" validate:"required_without=Username,required_without=Password"`
Username string `json:"username" validate:"required_without=APIKey"`
Password string `json:"password" validate:"required_without=APIKey"`}

How to extract values from local context in gofiber

I have managed to use the local context to set database query results using a custom middleware. I am trying to see how I can authenticate a user then pull their details from the database and inject it to the context. This has been done.
The local data on the final method on the route is actually an interface and I would like to extract fields from the data I set from the previous auth middleware. How can I work with this interface type to some form like a struct or json so that I can get the fields and values for doing some logic?
user := c.Locals("user")
fmt.Println("checking for locals",user)
From above user is of struct user
{
Name string `json:"name"`
Emain string `json:"email"`
ID string `json:"id"`
Password string `json:"password"`
}
How can I get the name and email ?
So after digging into the fiber docs and reading about interfaces and especially empty interfaces I think I have a solution but stand to be corrected
I saw one can cast an interface to a concrete type. In my case I would take the c.Locals("user") of type var user interface{}
then cast it to a struct passing the pointer to the user model as follows
user := c.Locals("user")
details, ok :=user.(*models.User)
fmt.Println("checking for locals -----------",details.Name)

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

One-to-many associations not working with test entries

Similar to this question, but in the case of one-to-many: Associations not working with test entries
I have two models User and E-Mails in GORM defined: File user.go
type User struct {
gorm.Model
Identity string `json:"identity"`
Password string `json:"password"`
Emails []Email
}
type Email struct {
gorm.Model
UserID uint
Text string `json:"text"`
Sender string `json:"sender"`
}
According to the documentation this should work with a test entry:
userRec := &user.User{ Identity: "John Wayne", Password: "mysecretpassword", Emails: []user.Email{user.Email{Text: "My Text", Sender: "julia#world.me"}, user.Email{Text: "My Text", Sender: "julia#world.me"}}}
However, the Email entries do not get associated with the User object.
Is it normal that the User object does not have entries to which Email objects it is referring to (as opposed to the "refer to" case)?
How can I query a User with all the corresponding Email objects?
All Emails are available via
var emails[] Email
db.Where("user_id = ?", id).Find(&emails)
You need to Preload (eager load) the emails table, by referring to its column name:
user := &User{}
db.Preload("Emails").First(user)
If you are using one-to-one relations, you can also do it automatically by calling:
db.Preload(clause.Associations).Find(user)
Note: This will not work for one-to-many relations.
There is some other functionality supported, such as nested Preloading, and combining joins and preloads together (for the purpose of filtering or ordering on sub-tables) defined in the GORM Docs

Go-Gorm: will the foreignkey be auto-populated when I set an object?

In the documentation we have this example:
type User struct {
gorm.Model
Name string
}
// `Profile` belongs to `User`, `UserID` is the foreign key
type Profile struct {
gorm.Model
UserID int
User User
Name string
}
If I do something like profile.User = &user, will that automatically populate the UserID field? Is it recommended to set both? Like:
profile.User = &user
profile.UserID = &user.ID
Or is that pointless? Furthermore, could I alternatively just set the UserID field and ignore the User field entirely?
If I do something like profile.User = &user, will that automatically populate the UserID field?
Just writing profile.User = &user will not populate the UserID field. Once you add the profile to the database. gorm will automatically populate the foreign key.
Is it recommended to set both?
Nope. In fact, you should not set the UserID yourself. This answers the last question as well.

Resources