From 72decd069b36e42209231ba62d4abe361a9484f0 Mon Sep 17 00:00:00 2001 From: black Date: Tue, 7 Feb 2023 16:26:41 +0800 Subject: [PATCH] fix: update panic if model is not ptr --- callbacks/callmethod.go | 3 +++ tests/hooks_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/callbacks/callmethod.go b/callbacks/callmethod.go index bcaa03f3..14b4bf9c 100644 --- a/callbacks/callmethod.go +++ b/callbacks/callmethod.go @@ -17,6 +17,9 @@ func callMethod(db *gorm.DB, fc func(value interface{}, tx *gorm.DB) bool) { db.Statement.CurDestIndex++ } case reflect.Struct: + if !db.Statement.ReflectValue.CanAddr() { + db.Statement.ReflectValue = reflect.New(db.Statement.ReflectValue.Type()).Elem() + } fc(db.Statement.ReflectValue.Addr().Interface(), tx) } } diff --git a/tests/hooks_test.go b/tests/hooks_test.go index 8e964fd8..6ef1151b 100644 --- a/tests/hooks_test.go +++ b/tests/hooks_test.go @@ -514,3 +514,33 @@ func TestFailedToSaveAssociationShouldRollback(t *testing.T) { t.Fatalf("AfterFind should not be called times:%d", productWithItem.Item.AfterFindCallTimes) } } + +type Product5 struct { + gorm.Model + Name string +} + +var beforeUpdateCall int + +func (p *Product5) BeforeUpdate(*gorm.DB) error { + beforeUpdateCall = beforeUpdateCall + 1 + return nil +} + +func TestUpdateCallbacks(t *testing.T) { + DB.Migrator().DropTable(&Product5{}) + DB.AutoMigrate(&Product5{}) + + p := Product5{Name: "unique_code"} + DB.Model(&Product5{}).Create(&p) + + DB.Model(&Product5{}).Where("id", p.ID).Update("name", "update_name_1") + if beforeUpdateCall != 1 { + t.Fatalf("before update should be called") + } + + DB.Model(Product5{}).Where("id", p.ID).Update("name", "update_name_2") + if beforeUpdateCall != 2 { + t.Fatalf("before update should be called") + } +}