I've got a one-to-one relationship, Location, working with postgresql:
type App struct {
gorm.Model
PersoID string `gorm:"primary_key;unique" json:"perso_id"`
Location OllyLocation `gorm:"foreignkey:location_id"`
LocationID *uint `json:"-" gorm:"type:integer REFERENCES locations(id)"`
Users []User `json:"users,omitempty" gorm:"many2many:app_users;"`
}
type Location struct {
ID uint `json:"-" gorm:"primary_key;unique"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time
Lat float64 `json:"lat"`
Long float64 `json:"long"`
Address string `json:"address"`
Country string `json:"country"`
}
But as you can see, the App structure has its own primaryKey id as string (and the GORM one). Thus this block from doing a simple db.Save()
from gorm.
So I've tried to do:
func (previousModel *App) UpdateAndReturnedUpdated(db *gorm.DB, appUpdated *App) error {
if err := db.Model(previousModel).Update(appUpdated).Error; err != nil {
return err
}
return db.Preload("Location").First(previousModel, App{PersoID: appUpdated.PersoID}).Error
}
With this, the App is correctly updated - fantastic! - but not the Location.
The location is re created in the db with the new values and the foreignKey LocationID is updated on the App.
This is super annoying because if I want to do an update of the address only without specifying other fields, they are just re created with the original type value (lat / long will be 0)
Any ideas about how to update the foreignKey? Thanks!
You can use this to not modify the associated entities
db.Set("gorm:save_associations", false).Save(previousModel)
or to save only one field of the struct
db.Model(previousModel).UpdateColumn("PersoID", appUpdated.PersoID)
if you want to update an associated entity and not the relation you will need to update the entity itself
db.Model(Location{ID:*previousModel.LocationID}).Update(appUpdated.Location)
Well, once more (but let's not blame the guy, he is alone) the main problem comes from an incomplete documentation.
All my problems were solved when I checked that I properly preloaded my foreign object + indicate it's ID (which blocked the fact that the foreignKey was Inserted instead of Updated)
Then, to be able to update it properly I had to do:
db.
Model(previousModel).
UpdateColumns(appUpdated).
Model(&previousModel.Location).
Updates(appUpdated.Location)
Was very painful, but at least it's solved.