I have two models User and Address in GORM defined:
File user.go
type User struct {
gorm.Model
Identity string `json:"identity"`
Password string `json:"password"`
Address Address
AddressID int
}
type Address struct {
gorm.Model
Street string `json:"street"`
StreetNumber string `json:"streetnumber"`
}
In the main.go file I initiate the DB, automigrate and want to add a test user to the DB:
database.InitDatabase()
database.DBConn.AutoMigrate(&user.User{})
database.DBConn.AutoMigrate(&user.Address{})
userRec := &user.User{ Identity: "John Wayne", Password: "mysecretpassword", Address: user.Address{Street: "Teststreet", StreetNumber: "1"}}
database.DBConn.Create(userRec)
The user gets created and the address as well, however, the address is not associated with the user, just
empty Address fields come up. What did I forget?
Is this the normal way to setup a test entry if you have associations in your entities (with nested models)?
Try using the "address_id" field as a foreignKey.
for example
type User struct {
gorm.Model
Identity string `json:"identity"`
Password string `json:"password"`
Address Address `gorm:"foreignKey:address_id;association_autoupdate:false"`
AddressID uint `json:"address_id"`
}
Online documentation
Maybe it will help.
Related
I'm using Go with Gorm many2many association from User and Role tables.
type User struct {
//gorm.Model
ID int64 `json:"id" gorm:"primary_key"`
Active sql.NullString ` json:"active " `
Email string `json:"email"`
FullName string `json:"full_name"`
Password string `json:"password"`
Username string `json:"username"`
Groups string `json:"groups"`
Otp string `json:"otp"`
CreatedTimeStamp time.Time `json:"created_time_stamp"`
UpdateTimeStamp time.Time `json:"update_time_stamp"`
LastLogin time.Time `json:"last_login"`
UserCount uint `json:"user_count" `
Roles []Role `gorm:"many2many:user_roles;"`
}
type Role struct {
//gorm.Model
ID int64 `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Users []User `gorm:"many2many:user_roles"`
}
using below code for delete user records and roles based on user id.
var roles []Role
db.Model(Role{}).Where("Name = ?", "ROLE_ADMIN").Take(&roles)
newUser := &User{
Email: user.Email,
FullName: user.FullName,
Username: user.Username,
Groups: groupCreation(user.Username),
Password: EncodePassword(user.Password),
CreatedTimeStamp: time.Now(),
UpdateTimeStamp: time.Now(),
LastLogin: time.Now(),
Roles: roles
}
db.Save(newUser)
**db.Model(&user).Association("Role").Delete(&newUser)**
Once executed last statement but didn't get delete(no impact) records from tables users and user_roles.
Kindly suggest me what is issue.
This code:
db.Model(&user).Association("Role").Delete(&newUser)
by the Gorm documentation:
Remove the relationship between source & arguments if exists, only delete the reference, won’t delete those objects from DB.
You need to use the Delete with Select https://gorm.io/docs/associations.html#Delete-with-Select
So actually it should be:
db.Select("Role").Delete(&newUser)
How to set unique at the struct specific columns. first name
type User struct {
ID int64 `orm:"size(100)", pk`
Lastname string `orm:"size(100)"`
Firstname string `orm:"size(100)"`
Role string `orm:"size(100)"`
Created time.Time `orm:"size(100)"`
Updated time.Time `orm:"size(100)"`
}
I'm using "github.com/astaxie/beego/orm"
According to the documentation, you just add the word "unique" to the tag:
Add unique key for one field
Name string `orm:"unique"`
To combine tags, you must use a semicolon as documented here. For example:
Firstname string orm:"unique;size(100)"
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)
Hypothetical, I run an API and when a user makes a GET request on the user resource, I will return relevant fields as a JSON
type User struct {
Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
Name string `json:"name,omitempty" bson:"name,omitempty"`
Secret string `json:"-,omitempty" bson:"secret,omitempty"`
}
As you can see, the Secret field in User has json:"-". This implies that in most operation that I would not like to return. In this case, a response would be
{
"id":1,
"Name": "John"
}
The field secret will not be returned as json:"-" omits the field.
Now, I am openning an admin only route where I would like to return the secret field. However, that would mean duplicating the User struct.
My current solution looks like this:
type adminUser struct {
Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
Name string `json:"name,omitempty" bson:"name,omitempty"`
Secret string `json:"secret,omitempty" bson:"secret,omitempty"`
}
Is there a way to embed User into adminUser? Kind of like inheritance:
type adminUser struct {
User
Secret string `json:"secret,omitempty" bson:"secret,omitempty"`
}
The above currently does not work, as only the field secret will be returned in this case.
Note: In the actual code base, there are few dozens fields. As such, the cost of duplicating code is high.
The actual mongo query is below:
func getUser(w http.ResponseWriter, r *http.Request) {
....omitted code...
var user adminUser
err := common.GetDB(r).C("users").Find(
bson.M{"_id": userId},
).One(&user)
if err != nil {
return
}
common.ServeJSON(w, &user)
}
You should take a look at the bson package's inline flag
(that is documented under bson.Marshal).
It should allow you to do something like this:
type adminUser struct {
User `bson:",inline"`
Secret string `json:"secret,omitempty" bson:"secret,omitempty"`
}
However, now you'll notice that you get duplicate key errors
when you try to read from the database with this structure,
since both adminUser and User contain the key secret.
In your case I would remove the Secret field from User
and only have the one in adminUser.
Then whenever you need to write to the secret field,
make sure you use an adminUser.
Another alternative would be to declare an interface.
type SecureModel interface {
SecureMe()
}
Make sure your model implements it:
type User struct {
Id bson.ObjectId `json:"id,omitempty" bson:"_id,omitempty"`
Username string `json:"username" bson:"username"`
Secret string `json:"secret,omitempty" bson:"secret"`
}
func (u *User) SecureMe() {
u.Secret = ""
}
And only call it depending on which route is called.
// I am being sent to a non-admin, secure me.
if _, ok := user.(SecureModel); ok {
user.(SecureModel).SecureMe()
}
// Marshall to JSON, etc.
...
Edit: The reason for using an interface here is for cases where you might send arbitrary models over the wire using a common method.
Can anyone help me, how to remove a belongs to association in go-gorm?
Here are my simple models:
type User struct {
gorm.Model
Name string
FirstName string
}
type Customer struct {
Notes []Note `gorm:"polymorphic:Owner;"` // other models can have notes as well
}
type Note struct {
gorm.Model
User User `json:"-"`
UserID uint
OwnerID uint
OwnerType string
}
For "Has many" and "Many to many" associations I can remove the relations. In this example, this works:
db.Model(&customer).Association("Notes").Delete(¬e)
However, if I try following:
db.Model(¬e).Association("User").Delete(&user)
I get a pointer error:
panic: runtime error: index out of range
... src/github.com/jinzhu/gorm/association.go:242 +0x21ce
The ''user'' and ''note'' objects exist and the relation is there (UserID is set to 1 in the database).