Skip to content

Commit

Permalink
fix: save with hook (#6285) (#6294)
Browse files Browse the repository at this point in the history
  • Loading branch information
black-06 committed May 26, 2023
1 parent 812bb20 commit 11fdf46
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
2 changes: 1 addition & 1 deletion finisher_api.go
Expand Up @@ -105,7 +105,7 @@ func (db *DB) Save(value interface{}) (tx *DB) {
updateTx := tx.callbacks.Update().Execute(tx.Session(&Session{Initialized: true}))

if updateTx.Error == nil && updateTx.RowsAffected == 0 && !updateTx.DryRun && !selectedUpdate {
return tx.Clauses(clause.OnConflict{UpdateAll: true}).Create(value)
return tx.Session(&Session{SkipHooks: true}).Clauses(clause.OnConflict{UpdateAll: true}).Create(value)

This comment has been minimized.

Copy link
@pedroreys

pedroreys Feb 19, 2024

hey folks, this introduced a breaking change.

Prior to this change, when calling .Save both BeforeCreate and BeforeUpdate hooks were called. But after this change, only BeforeUpdate is called when the PK field is predefined.

}

return updateTx
Expand Down
73 changes: 73 additions & 0 deletions tests/update_test.go
Expand Up @@ -809,3 +809,76 @@ func TestUpdateWithDiffSchema(t *testing.T) {
AssertEqual(t, err, nil)
AssertEqual(t, "update-diff-schema-2", user.Name)
}

type TokenOwner struct {
ID int
Name string
Token Token `gorm:"foreignKey:UserID"`
}

func (t *TokenOwner) BeforeSave(tx *gorm.DB) error {
t.Name += "_name"
return nil
}

type Token struct {
UserID int `gorm:"primary_key"`
Content string `gorm:"type:varchar(100)"`
}

func (t *Token) BeforeSave(tx *gorm.DB) error {
t.Content += "_encrypted"
return nil
}

func TestSaveWithHooks(t *testing.T) {
DB.Migrator().DropTable(&Token{}, &TokenOwner{})
DB.AutoMigrate(&Token{}, &TokenOwner{})

saveTokenOwner := func(owner *TokenOwner) (*TokenOwner, error) {
var newOwner TokenOwner
if err := DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Debug().Session(&gorm.Session{FullSaveAssociations: true}).Save(owner).Error; err != nil {
return err
}
if err := tx.Preload("Token").First(&newOwner, owner.ID).Error; err != nil {
return err
}
return nil
}); err != nil {
return nil, err
}
return &newOwner, nil
}

owner := TokenOwner{
Name: "user",
Token: Token{Content: "token"},
}
o1, err := saveTokenOwner(&owner)
if err != nil {
t.Errorf("failed to save token owner, got error: %v", err)
}
if o1.Name != "user_name" {
t.Errorf(`owner name should be "user_name", but got: "%s"`, o1.Name)
}
if o1.Token.Content != "token_encrypted" {
t.Errorf(`token content should be "token_encrypted", but got: "%s"`, o1.Token.Content)
}

owner = TokenOwner{
ID: owner.ID,
Name: "user",
Token: Token{Content: "token2"},
}
o2, err := saveTokenOwner(&owner)
if err != nil {
t.Errorf("failed to save token owner, got error: %v", err)
}
if o2.Name != "user_name" {
t.Errorf(`owner name should be "user_name", but got: "%s"`, o2.Name)
}
if o2.Token.Content != "token2_encrypted" {
t.Errorf(`token content should be "token2_encrypted", but got: "%s"`, o2.Token.Content)
}
}

0 comments on commit 11fdf46

Please sign in to comment.