Skip to content

Commit d3c3d20

Browse files
authored
✨ feat: support table migrate (#47)
1 parent 2c2bd70 commit d3c3d20

File tree

3 files changed

+91
-21
lines changed

3 files changed

+91
-21
lines changed

virtual/model/field.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type Field struct {
3030
DefaultValue string `json:"defaultValue" yaml:"defaultValue"`
3131
DefaultValueFN func() string `json:"-" yaml:"-"`
3232
NotNull bool `json:"notNull" yaml:"notNull"`
33-
Unique bool `json:"unique" yaml:"unique"`
33+
Unique string `json:"unique" yaml:"unique"`
3434
Index string `json:"index" yaml:"index"`
3535
Comment string `json:"comment" yaml:"comment"`
3636
Size int `json:"size" yaml:"size"`
@@ -71,9 +71,22 @@ func (f *Field) GetName() string {
7171
}
7272

7373
func (f *Field) MakeField() reflect.StructField {
74+
gormTag := fmt.Sprintf(`gorm:"column:%s`, f.Name)
75+
if f.Size > 0 {
76+
gormTag = fmt.Sprintf(`%s;size:%d`, gormTag, f.Size)
77+
}
78+
if f.Index != "" {
79+
gormTag = fmt.Sprintf(`%s;index:%s`, gormTag, f.Index)
80+
}
81+
if f.NotNull {
82+
gormTag = fmt.Sprintf(`%s;not null`, gormTag)
83+
}
84+
if f.Unique != "" {
85+
gormTag = fmt.Sprintf(`%s;unique:%s`, gormTag, f.Unique)
86+
}
7487
field := reflect.StructField{
7588
Name: f.GetName(),
76-
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s" gorm:"column:%s"`, f.JsonTag, f.Name)),
89+
Tag: reflect.StructTag(fmt.Sprintf(`json:"%s,omitempty" %s"`, f.JsonTag, gormTag)),
7790
}
7891
switch f.DataType {
7992
case schema.Bool:

virtual/model/model.go

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"fmt"
55
"reflect"
66
"strings"
7+
"time"
78

89
"github.com/gin-gonic/gin"
910
"gorm.io/gorm"
10-
"gorm.io/gorm/schema"
1111
)
1212

1313
/*
@@ -18,11 +18,9 @@ import (
1818
*/
1919

2020
type Model struct {
21-
Table string `json:"tableName" yaml:"tableName" binding:"required"`
22-
AutoCreateTime schema.TimeType `json:"autoCreateTime" yaml:"autoCreateTime"`
23-
AutoUpdateTime schema.TimeType `json:"autoUpdateTime" yaml:"autoUpdateTime"`
24-
HardDeleted bool `json:"hardDeleted" yaml:"hardDeleted"`
25-
Fields []*Field `json:"fields" yaml:"fields" binding:"required"`
21+
Table string `json:"tableName" yaml:"tableName" binding:"required"`
22+
HardDeleted bool `json:"hardDeleted" yaml:"hardDeleted"`
23+
Fields []*Field `json:"fields" yaml:"fields" binding:"required"`
2624
}
2725

2826
// TableName get table name
@@ -42,12 +40,6 @@ func (m *Model) PrimaryKeys() []string {
4240
}
4341

4442
func (m *Model) Init() {
45-
if m.AutoCreateTime == 0 {
46-
m.AutoCreateTime = schema.UnixSecond
47-
}
48-
if m.AutoUpdateTime == 0 {
49-
m.AutoUpdateTime = schema.UnixSecond
50-
}
5143
for i := range m.Fields {
5244
m.Fields[i].Init()
5345
}
@@ -68,20 +60,49 @@ func (m *Model) Default(data any) {
6860

6961
// MakeModel make virtual model
7062
func (m *Model) MakeModel() any {
71-
fieldTypes := make([]reflect.StructField, 0)
72-
for i := range m.Fields {
73-
fieldTypes = append(fieldTypes, m.Fields[i].MakeField())
74-
}
75-
return reflect.New(reflect.StructOf(fieldTypes)).Interface()
63+
m.Init()
64+
s := reflect.New(reflect.StructOf(m.MakeField()))
65+
return s.Interface()
7666
}
7767

7868
func (m *Model) MakeList() any {
7969
m.Init()
70+
return reflect.New(reflect.SliceOf(reflect.StructOf(m.MakeField()))).Interface()
71+
}
72+
73+
func (m *Model) Migrate(db *gorm.DB) error {
74+
return db.Table(m.TableName()).AutoMigrate(m.MakeModel())
75+
}
76+
77+
func (m *Model) MakeField() []reflect.StructField {
8078
fieldTypes := make([]reflect.StructField, 0)
8179
for i := range m.Fields {
8280
fieldTypes = append(fieldTypes, m.Fields[i].MakeField())
8381
}
84-
return reflect.New(reflect.SliceOf(reflect.StructOf(fieldTypes))).Interface()
82+
fieldTypes = append(fieldTypes, m.MakeTimeField()...)
83+
return fieldTypes
84+
}
85+
86+
func (m *Model) MakeTimeField() []reflect.StructField {
87+
fieldTypes := []reflect.StructField{
88+
{
89+
Name: "CreatedAt",
90+
Type: reflect.TypeOf(time.Time{}),
91+
Tag: "json:\"createdAt,omitempty\"",
92+
}, {
93+
Name: "UpdatedAt",
94+
Type: reflect.TypeOf(time.Time{}),
95+
Tag: "json:\"updatedAt,omitempty\"",
96+
},
97+
}
98+
if !m.HardDeleted {
99+
fieldTypes = append(fieldTypes, reflect.StructField{
100+
Name: "DeletedAt",
101+
Type: reflect.TypeOf(gorm.DeletedAt{}),
102+
Tag: "json:\"deletedAt,omitempty\" gorm:\"index\"",
103+
})
104+
}
105+
return fieldTypes
85106
}
86107

87108
func (m *Model) TableScope(db *gorm.DB) *gorm.DB {

virtual/model/model_test.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,42 @@ func TestModel_TableName(t *testing.T) {
8787
}
8888
}
8989

90+
func TestModel_Migrate(t *testing.T) {
91+
tests := []struct {
92+
name string
93+
path string
94+
dsn string
95+
wantError bool
96+
}{
97+
{
98+
name: "test0",
99+
path: "../../testdata/test.yml",
100+
dsn: "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local",
101+
wantError: false,
102+
},
103+
}
104+
for _, tt := range tests {
105+
rb, err := os.ReadFile(tt.path)
106+
if err != nil {
107+
t.Fatalf("ReadFile() error = %v", err)
108+
}
109+
m := &Model{}
110+
err = yaml.Unmarshal(rb, m)
111+
if err != nil {
112+
t.Fatalf("Unmarshal() error = %v", err)
113+
}
114+
db, err := gorm.Open(mysql.New(mysql.Config{
115+
DSN: tt.dsn,
116+
}))
117+
if err != nil {
118+
t.Fatalf("Open() error = %v", err)
119+
}
120+
if err = m.Migrate(db); (err != nil) != tt.wantError {
121+
t.Errorf("Migrate() error = %v, wantError %v", err, tt.wantError)
122+
}
123+
}
124+
}
125+
90126
func TestModel_Create(t *testing.T) {
91127
tests := []struct {
92128
name string
@@ -254,7 +290,7 @@ func TestModel_Delete(t *testing.T) {
254290
req, _ := http.NewRequest(http.MethodDelete, "/test/"+id, nil)
255291
r := gin.Default()
256292
r.DELETE("/test/:id", func(ctx *gin.Context) {
257-
if err = db.Scopes(m.URI(ctx)).Delete(nil).Error; err != nil {
293+
if err = db.Scopes(m.URI(ctx)).Delete(m.MakeModel()).Error; err != nil {
258294
ctx.Status(http.StatusInternalServerError)
259295
t.Fatalf("Delete() error = %v", err)
260296
}

0 commit comments

Comments
 (0)