GORM Playground Link
Here is my playground link: https://github.com/go-gorm/playground/pull/596. I've reproduced the models.go and main_test.go below:
main_test.go:
func TestGORM(t *testing.T) {
user := User{Name: "jinzhu"}
DB.Create(&user)
var result User
if err := DB.First(&result, user.ID).Error; err != nil {
t.Errorf("Failed, got error: %v", err)
}
familiar := Familiar{Name: "fam"}
familiarIDBefore := familiar.Id
DB.Create(&familiar)
familiarIDAfter := familiar.Id
if familiarIDBefore == familiarIDAfter {
t.Errorf("Familiar ID should be created")
}
meeting := Meeting{IsLive: true}
DB.Create(&meeting)
familiars := []Familiar{familiar}
meetingFamiliars := meeting.Familiars
if len(meetingFamiliars) > 0 {
t.Errorf("Meeting should not have any familiars yet")
}
DB.Model(&meeting).Association("Familiars").Append(familiars)
meetingFamiliars = meeting.Familiars
if len(meetingFamiliars) != 1 {
t.Errorf("Meeting should have a familiar now")
}
familiarInMeetingID := meetingFamiliars[0].Id
familiarIDAfterMeetingAdd := familiar.Id
if familiarIDAfterMeetingAdd != familiarIDAfter {
t.Errorf("Familiar ID should not be changed")
}
if familiarInMeetingID != familiarIDAfter {
t.Errorf("Familiar ID should be the same. Meeting familiar ID: %v, familiar ID: %v", familiarInMeetingID, familiarIDAfter)
}
}
models.go:
type Language struct {
Code string `gorm:"primarykey"`
Name string
}
type Meeting struct {
gorm.Model
Id string `gorm:"type:uuid;primaryKey" json:"id"`
IsLive bool `json:"isLive"`
CompletedAt time.Time `json:"completedAt"`
Familiars []Familiar `gorm:"many2many:familiar_meetings;"`
}
func (m *Meeting) BeforeCreate(tx *gorm.DB) (err error) {
// UUID version 4
m.Id = uuid.NewString()
return
}
type Familiar struct {
gorm.Model
Id string `gorm:"type:uuid;primaryKey" json:"id"`
Meetings []Meeting `gorm:"many2many:familiar_meetings;"`
Name string `json:"name"`
}
func (f *Familiar) BeforeCreate(tx *gorm.DB) (err error) {
// UUID version 4
f.Id = uuid.NewString()
return
}
Description
The issue is that BeforeCreate is called on children being added to a many2many. Because I'm using BeforeCreate to do uuids, this is changing the Id of the object being added to the many2many.
Besides the bug, is there a better way to do what I'm trying to do? I'm new to gorm.
Comment From: github-actions[bot]
The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout https://github.com/go-gorm/playground for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the Question template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ Search Before Asking ✨
Comment From: Poisonwind
I have the same problem. After "BeforeCreate" was added to base model (id). Gorm started to create all child models with base model (id) in it or change its uuid.
Comment From: black-06
try this model
type Familiar struct {
ID string `gorm:"type:uuid;primaryKey" json:"id"`
Meetings []Meeting `gorm:"many2many:familiar_meetings;"`
Name string `json:"name"`
}
func (f *Familiar) BeforeCreate(tx *gorm.DB) (err error) {
if f.ID == "" {
// UUID version 4
f.ID = uuid.NewString()
}
return
}
Association.Append will try INSERT ... ON CONFLICT DO NOTHING.
So we need to keep primaryKey if it already exists.
Comment From: cinjon
Are you suggesting dropping the gorm.Model from the model definition? That's the main change I see here.
Comment From: black-06
Are you suggesting dropping the gorm.Model from the model definition? That's the main change I see here.
it's if f.ID == ""
Comment From: black-06
Or try to skip auto create/update, https://gorm.io/docs/associations.html#Skip-Auto-Create-x2F-Update