Skip to content

Commit 1e8baf5

Browse files
authored
fixes #7486 (#7492)
* fixes #7486 * Added A test case for subset changes of model * completed the test file for check_subset_model_change_test.go
1 parent 842ee52 commit 1e8baf5

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

schema/field.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ func (field *Field) setupValuerAndSetter() {
457457
switch {
458458
case len(field.StructField.Index) == 1 && fieldIndex > 0:
459459
field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
460-
fieldValue := reflect.Indirect(value).Field(fieldIndex)
460+
fieldValue := reflect.Indirect(value).FieldByName(field.Name)
461461
return fieldValue.Interface(), fieldValue.IsZero()
462462
}
463463
default:
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package tests_test
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"gorm.io/gorm"
9+
)
10+
11+
type Man struct {
12+
ID int
13+
Age int
14+
Name string
15+
Detail string
16+
}
17+
18+
// Panic-safe BeforeUpdate hook that checks for Changed("age")
19+
func (m *Man) BeforeUpdate(tx *gorm.DB) (err error) {
20+
defer func() {
21+
if r := recover(); r != nil {
22+
err = fmt.Errorf("panic in BeforeUpdate: %v", r)
23+
}
24+
}()
25+
26+
if !tx.Statement.Changed("age") {
27+
return nil
28+
}
29+
return nil
30+
}
31+
32+
func (m *Man) update(data interface{}) error {
33+
return DB.Set("data", data).Model(m).Where("id = ?", m.ID).Updates(data).Error
34+
}
35+
36+
func TestBeforeUpdateStatementChanged(t *testing.T) {
37+
DB.AutoMigrate(&Man{})
38+
type TestCase struct {
39+
BaseObjects Man
40+
change interface{}
41+
expectError bool
42+
}
43+
44+
testCases := []TestCase{
45+
{
46+
BaseObjects: Man{ID: 1, Age: 18, Name: "random-name"},
47+
change: struct {
48+
Age int
49+
}{Age: 20},
50+
expectError: false,
51+
},
52+
{
53+
BaseObjects: Man{ID: 2, Age: 18, Name: "random-name"},
54+
change: struct {
55+
Name string
56+
}{Name: "name-only"},
57+
expectError: true,
58+
},
59+
{
60+
BaseObjects: Man{ID: 2, Age: 18, Name: "random-name"},
61+
change: struct {
62+
Name string
63+
Age int
64+
}{Name: "name-only", Age: 20},
65+
expectError: false,
66+
},
67+
}
68+
69+
for _, test := range testCases {
70+
DB.Create(&test.BaseObjects)
71+
72+
// below comment is stored for future reference
73+
// err := DB.Set("data", test.change).Model(&test.BaseObjects).Where("id = ?", test.BaseObjects.ID).Updates(test.change).Error
74+
err := test.BaseObjects.update(test.change)
75+
if strings.Contains(fmt.Sprint(err), "panic in BeforeUpdate") {
76+
if !test.expectError {
77+
t.Errorf("unexpected panic in BeforeUpdate for input: %+v\nerror: %v", test.change, err)
78+
}
79+
} else {
80+
if test.expectError {
81+
t.Errorf("expected panic did not occur for input: %+v", test.change)
82+
}
83+
if err != nil {
84+
t.Errorf("unexpected GORM error: %v", err)
85+
}
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)