0x4a52466c696e74 2 semanas atrás
pai
commit
0e773414ef
2 arquivos alterados com 146 adições e 0 exclusões
  1. 76 0
      rest_gorm/preload.go
  2. 70 0
      rest_gorm/z_test.go

+ 76 - 0
rest_gorm/preload.go

@@ -0,0 +1,76 @@
+package rest_gorm
+
+import (
+	"fmt"
+	"log"
+	"reflect"
+	"strings"
+
+	"git.ali33.ru/fcg-xvii/rest"
+	"gorm.io/gorm"
+)
+
+func Preload(obj any, fields rest.FieldList, q *gorm.DB) (*gorm.DB, error) {
+	return preloadPrefix(obj, fields, q, "")
+}
+
+func preloadPrefix(obj any, fields rest.FieldList, q *gorm.DB, prefix string) (*gorm.DB, error) {
+	val := reflect.ValueOf(obj)
+	names, err := namesExt(val)
+	if err != nil {
+		return nil, err
+	}
+	for _, name := range names {
+		if f, check := fields.Field(name.eName); check {
+			q = q.Preload(prefix + name.eName)
+			if f.IsObject() {
+				log.Println("is_object:" + prefix + name.eName)
+				if q, err = preloadPrefix(name.eValue, f.Names, q, prefix+name.eName+"."); err != nil {
+					return nil, err
+				}
+			}
+		}
+	}
+	return q, nil
+}
+
+type eExtName struct {
+	eName  string
+	eValue any
+}
+
+func fElemType(t reflect.Type) reflect.Type {
+	switch t.Kind() {
+	case reflect.Ptr, reflect.Interface, reflect.Slice:
+		return fElemType(t.Elem())
+	}
+	return t
+}
+
+func namesExt(val reflect.Value) (res []eExtName, err error) {
+
+	k := val.Kind()
+	switch k {
+	case reflect.Ptr, reflect.Interface, reflect.Slice:
+		return namesExt(val.Elem())
+	}
+	if k != reflect.Struct {
+		return nil, fmt.Errorf("type [ %v ] is not a struct", k)
+	}
+	t := reflect.TypeOf(val.Interface())
+	for i := 0; i < t.NumField(); i++ {
+		fType := t.Field(i)
+		tag := fType.Tag.Get("rest")
+		if len(tag) > 0 && strings.Contains(tag, "ext") {
+			rVal := reflect.New(fElemType(fType.Type))
+			res = append(
+				res,
+				eExtName{
+					eName:  fType.Name,
+					eValue: rVal.Interface(),
+				},
+			)
+		}
+	}
+	return
+}

+ 70 - 0
rest_gorm/z_test.go

@@ -0,0 +1,70 @@
+package rest_gorm
+
+import (
+	"reflect"
+	"testing"
+
+	"git.ali33.ru/fcg-xvii/rest"
+)
+
+type ExtSize struct {
+	ID int
+}
+
+type NameExtChild struct {
+	ID   int
+	Name string
+	Size *ExtSize `rest:"ext"`
+}
+
+type NameExt struct {
+	ID         int
+	Name       string
+	ExtPointer *NameExtChild  `rest:"ext"`
+	ExtSlice   []NameExtChild `rest:"ext"`
+	ExtStruct  NameExtChild   `rest:"ext"`
+}
+
+func TestNamesExt(t *testing.T) {
+	//i := 10
+	//r := reflect.ValueOf(&i)
+	r := reflect.ValueOf(&NameExt{})
+	//rType := reflect.TypeOf(r.Type())
+	res, err := namesExt(r)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, v := range res {
+		t.Log(v.eName, reflect.ValueOf(v.eValue).Elem().Type())
+	}
+	t.Log(res)
+}
+
+func TestPreload(t *testing.T) {
+	fields := rest.FieldList{
+		&rest.Field{
+			Name: "ExtStruct",
+			Names: rest.FieldList{
+				&rest.Field{
+					Name: "Size",
+				},
+			},
+		},
+		&rest.Field{
+			Name: "ExtSlice",
+		},
+		&rest.Field{
+			Name: "ExtPointer",
+			Names: rest.FieldList{
+				&rest.Field{
+					Name: "Size",
+				},
+			},
+		},
+	}
+	val := &NameExt{}
+	_, err := Preload(val, fields, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}