|
@@ -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
|
|
|
|
+}
|