-
-
Couldn't load subscription status.
- Fork 4.1k
Closed
Labels
Description
GORM Playground Link
Description
When you save a model which BeforeSave is implemented in a transaction, BeforeSave will be executed twice.
package main_test
import (
"testing"
"github.com/stretchr/testify/assert"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func Test_main(t *testing.T) {
dsn := "root:pass@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn))
assert.NoError(t, err)
assert.NoError(t, db.AutoMigrate(&User{}, &Token{}))
u := User{
Name: "user",
Token: Token{
Content: "token",
},
}
u1, err := saveUser(db, &u)
assert.NoError(t, err)
assert.Equal(t, "token_encrypted", u1.Token.Content)
u = User{
ID: u.ID,
Name: "user",
Token: Token{
Content: "token2",
},
}
u2, err := saveUser(db, &u)
assert.NoError(t, err)
assert.Equal(t, "token2_encrypted", u2.Token.Content) // FAIL: actual is token2_encrypted_encrypted
}
func saveUser(db *gorm.DB, u *User) (*User, error) {
var newUser User
if err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Debug().Session(&gorm.Session{FullSaveAssociations: true}).Save(u).Error; err != nil {
return err
}
if err := tx.Preload("Token").First(&newUser, u.ID).Error; err != nil {
return err
}
return nil
}); err != nil {
return nil, err
}
return &newUser, nil
}
// - Models
type User struct {
ID int `gorm:"primary_key"`
Name string `gorm:"type:varchar(100)"`
Token Token `gorm:"foreignKey:UserID"`
}
type Token struct {
UserID int `gorm:"primary_key"`
Content string `gorm:"type:varchar(100)"`
}
// This method should be called only once
func (t *Token) BeforeSave(tx *gorm.DB) error {
t.Content += "_encrypted"
return nil
}$ go test main_test.go
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[2.085ms] [rows:1] INSERT INTO `tokens` (`content`,`user_id`) VALUES ('token_encrypted',7) ON DUPLICATE KEY UPDATE `content`=VALUES(`content`)
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[5.084ms] [rows:1] INSERT INTO `users` (`name`) VALUES ('user')
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[2.312ms] [rows:2] INSERT INTO `tokens` (`content`,`user_id`) VALUES ('token2_encrypted',7) ON DUPLICATE KEY UPDATE `content`=VALUES(`content`)
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[4.827ms] [rows:0] UPDATE `users` SET `name`='user' WHERE `id` = 7
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[2.382ms] [rows:2] INSERT INTO `tokens` (`content`,`user_id`) VALUES ('token2_encrypted_encrypted',7) ON DUPLICATE KEY UPDATE `content`=VALUES(`content`)
2023/05/01 11:00:35 /home/ras/misc/go/gorm/main_test.go:42
[5.107ms] [rows:0] INSERT INTO `users` (`name`,`id`) VALUES ('user',7) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`)
--- FAIL: Test_main (0.12s)
main_test.go:36:
Error Trace: /home/ras/misc/go/gorm/main_test.go:36
Error: Not equal:
expected: "token2_encrypted"
actual : "token2_encrypted_encrypted"
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-token2_encrypted
+token2_encrypted_encrypted
Test: Test_main
FAIL
FAIL command-line-arguments 0.125s
FAIL