feat: add handling for the interface field, when an Interface field is an object that has already been instantiated, use the type of the instantiated object itself instead of interface{}.
This commit is contained in:
parent
9c2c0d2414
commit
1ad2d97df9
@ -115,7 +115,6 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
|
|||||||
value = reflect.New(value.Type().Elem())
|
value = reflect.New(value.Type().Elem())
|
||||||
}
|
}
|
||||||
|
|
||||||
modelValue := reflect.Indirect(value)
|
|
||||||
modelType := reflect.Indirect(value).Type()
|
modelType := reflect.Indirect(value).Type()
|
||||||
|
|
||||||
if modelType.Kind() == reflect.Interface {
|
if modelType.Kind() == reflect.Interface {
|
||||||
@ -150,6 +149,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
|
|||||||
return s, s.err
|
return s, s.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modelValue := reflect.New(modelType)
|
||||||
tableName := namer.TableName(modelType.Name())
|
tableName := namer.TableName(modelType.Name())
|
||||||
if tabler, ok := modelValue.Interface().(Tabler); ok {
|
if tabler, ok := modelValue.Interface().(Tabler); ok {
|
||||||
tableName = tabler.TableName()
|
tableName = tabler.TableName()
|
||||||
@ -166,7 +166,7 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
|
|||||||
|
|
||||||
schema := &Schema{
|
schema := &Schema{
|
||||||
Name: modelType.Name(),
|
Name: modelType.Name(),
|
||||||
ModelValue: modelValue,
|
ModelValue: reflect.Indirect(value),
|
||||||
ModelType: modelType,
|
ModelType: modelType,
|
||||||
Table: tableName,
|
Table: tableName,
|
||||||
FieldsByName: map[string]*Field{},
|
FieldsByName: map[string]*Field{},
|
||||||
|
23
tests/interface_test.go
Normal file
23
tests/interface_test.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package tests_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gorm.io/gorm/utils/tests"
|
||||||
|
. "gorm.io/gorm/utils/tests"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInterface(t *testing.T) {
|
||||||
|
vehicleWrite := &tests.Vehicle{Meta: &tests.MotorMeta{Power: "electric"}}
|
||||||
|
|
||||||
|
if err := DB.Create(vehicleWrite).Error; err != nil {
|
||||||
|
t.Fatalf("fail to create region %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vehicleRead := &tests.Vehicle{Meta: &tests.MotorMeta{}}
|
||||||
|
if err := DB.Debug().First(vehicleRead, "id = ?", vehicleWrite.ID).Error; err != nil {
|
||||||
|
t.Fatalf("fail to find vehicle %v", err)
|
||||||
|
} else {
|
||||||
|
AssertEqual(t, vehicleWrite.Meta.(*tests.MotorMeta).Power, vehicleRead.Meta.(*tests.MotorMeta).Power)
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import (
|
|||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/driver/sqlserver"
|
"gorm.io/driver/sqlserver"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
. "gorm.io/gorm/utils/tests"
|
. "gorm.io/gorm/utils/tests"
|
||||||
@ -107,7 +108,7 @@ func OpenTestConnection() (db *gorm.DB, err error) {
|
|||||||
|
|
||||||
func RunMigrations() {
|
func RunMigrations() {
|
||||||
var err error
|
var err error
|
||||||
allModels := []interface{}{&User{}, &Account{}, &Pet{}, &Company{}, &Toy{}, &Language{}, &Coupon{}, &CouponProduct{}, &Order{}, &Parent{}, &Child{}}
|
allModels := []interface{}{&User{}, &Account{}, &Pet{}, &Company{}, &Toy{}, &Language{}, &Coupon{}, &CouponProduct{}, &Order{}, &Parent{}, &Child{}, &Vehicle{Meta: &MotorMeta{}}}
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] })
|
rand.Shuffle(len(allModels), func(i, j int) { allModels[i], allModels[j] = allModels[j], allModels[i] })
|
||||||
|
|
||||||
|
@ -2,6 +2,10 @@ package tests
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -94,3 +98,62 @@ type Child struct {
|
|||||||
ParentID *uint
|
ParentID *uint
|
||||||
Parent *Parent
|
Parent *Parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Meta interface {
|
||||||
|
Scan(src interface{}) error
|
||||||
|
Value() (driver.Value, error)
|
||||||
|
GormDataType() string
|
||||||
|
}
|
||||||
|
type MotorMeta struct {
|
||||||
|
Power string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (meta *MotorMeta) Scan(src interface{}) error {
|
||||||
|
bytes, ok := src.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return errors.New(fmt.Sprint("Failed to unmarshal JSON value:", src))
|
||||||
|
}
|
||||||
|
result := MotorMeta{}
|
||||||
|
err := json.Unmarshal(bytes, &result)
|
||||||
|
*meta = result
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (meta *MotorMeta) Value() (driver.Value, error) {
|
||||||
|
if meta == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
res, err := json.Marshal(meta)
|
||||||
|
return string(res), err
|
||||||
|
}
|
||||||
|
func (MotorMeta) GormDataType() string {
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
|
||||||
|
type ManualMeta struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (meta *ManualMeta) Scan(src interface{}) error {
|
||||||
|
bytes, ok := src.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return errors.New(fmt.Sprint("Failed to unmarshal JSON value:", src))
|
||||||
|
}
|
||||||
|
result := ManualMeta{}
|
||||||
|
err := json.Unmarshal(bytes, &result)
|
||||||
|
*meta = result
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (meta *ManualMeta) Value() (driver.Value, error) {
|
||||||
|
if meta == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
res, err := json.Marshal(meta)
|
||||||
|
return string(res), err
|
||||||
|
}
|
||||||
|
func (ManualMeta) GormDataType() string {
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
|
||||||
|
type Vehicle struct {
|
||||||
|
gorm.Model
|
||||||
|
Meta Meta
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user