My models uses random strings as Primery Key which is generated using _BeforeCreate_ callback. Everything works, but when I try to persist an Object with its Associations I'm getting this error:
[0.71ms] INSERT INTO "hands" ("id","name") VALUES ('75','left') RETURNING "hands"."id"
pq: null value in column "id" violates not-null constraint
pq: null value in column "id" violates not-null constraint
[1.46ms] INSERT INTO "fingers" ("hand_id","name") VALUES ('75','a') RETURNING "fingers"."id"
So it seem that GORM is not assigning the ID to Fingers when performing the INSERT
This is a sample code that reproduce the issue:
package main
import (
"fmt"
"math/rand"
"time"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)
func randomString() string {
rand.Seed(time.Now().UnixNano())
return fmt.Sprintf("%d", rand.Intn(100))
}
type Finger struct {
ID string `gorm:"primary_key"`
HandID string
Name string
}
func (f *Finger) BeforeCreate() error {
r := randomString()
f.ID = r
return nil
}
type Hand struct {
ID string `gorm:"primary_key"`
Name string
Fingers []Finger
}
func (h *Hand) BeforeCreate() error {
r := randomString()
h.ID = r
return nil
}
func main() {
db, _ := gorm.Open("postgres", "user=postgres sslmode=disable")
db.Debug().AutoMigrate(&Hand{}, &Finger{})
h := &Hand{
Name: "left",
Fingers: []Finger{
Finger{Name: "a"}, Finger{Name: "b"},
},
}
db.Debug().Create(h)
}
I'm I doing something wrong?
Hi @gchaincl
It needs to be written like this:
func (h *Hand) BeforeCreate(scope *gorm.Scope) error {
scope.SetColumn("ID", randomString())
return nil
}
In callbacks, if you want to update any columns to database, has to use SetColumn, this wasn't documented before, will add this to the v1 release.
Thank you.
Please reopen this issue as it is not fixed , nor is it documented anywhere. I've just spent a whole day on this.
I had a function very similar to this one:
func (h *Hand) BeforeCreate() error {
h.ID = someRandomID
return nil
}
Having to set the value via scope.setColumn is not documented anywhere , just referenced in some places , but no clear indication on why you should do it that way.
Having the function applied to a pointer made me think that I am supposed to modify that object , as if that object was the final object that will get sent to the DB. That was confusing.
Thanks
Mircea
Most helpful comment
Please reopen this issue as it is not fixed , nor is it documented anywhere. I've just spent a whole day on this.
I had a function very similar to this one:
Having to set the value via scope.setColumn is not documented anywhere , just referenced in some places , but no clear indication on why you should do it that way.
Having the function applied to a pointer made me think that I am supposed to modify that object , as if that object was the final object that will get sent to the DB. That was confusing.
Thanks
Mircea