preload.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package rest_gorm
  2. import (
  3. "fmt"
  4. "log"
  5. "reflect"
  6. "strings"
  7. "git.ali33.ru/fcg-xvii/rest"
  8. "gorm.io/gorm"
  9. )
  10. func Preload(obj any, fields rest.FieldList, q *gorm.DB) (*gorm.DB, error) {
  11. return preloadPrefix(obj, fields, q, "")
  12. }
  13. func preloadPrefix(obj any, fields rest.FieldList, q *gorm.DB, prefix string) (*gorm.DB, error) {
  14. val := reflect.ValueOf(obj)
  15. names, err := namesExt(val)
  16. if err != nil {
  17. return nil, err
  18. }
  19. for _, name := range names {
  20. if f, check := fields.Field(name.eName); check {
  21. log.Println("preload", prefix+name.eName)
  22. q = q.Preload(prefix + name.eName)
  23. if f.IsObject() {
  24. log.Println("is_object:" + prefix + name.eName)
  25. if q, err = preloadPrefix(name.eValue, f.Names, q, prefix+name.eName+"."); err != nil {
  26. return nil, err
  27. }
  28. }
  29. }
  30. }
  31. return q, nil
  32. }
  33. type eExtName struct {
  34. eName string
  35. eValue any
  36. }
  37. func fElemType(t reflect.Type) reflect.Type {
  38. switch t.Kind() {
  39. case reflect.Ptr, reflect.Interface, reflect.Slice:
  40. return fElemType(t.Elem())
  41. }
  42. return t
  43. }
  44. func namesExt(val reflect.Value) (res []eExtName, err error) {
  45. k := val.Kind()
  46. switch k {
  47. case reflect.Ptr, reflect.Interface, reflect.Slice:
  48. return namesExt(val.Elem())
  49. }
  50. if k != reflect.Struct {
  51. return nil, fmt.Errorf("type [ %v ] is not a struct", k)
  52. }
  53. t := reflect.TypeOf(val.Interface())
  54. for i := 0; i < t.NumField(); i++ {
  55. fType := t.Field(i)
  56. tag := fType.Tag.Get("rest")
  57. if len(tag) > 0 && strings.Contains(tag, "ext") {
  58. rVal := reflect.New(fElemType(fType.Type))
  59. res = append(
  60. res,
  61. eExtName{
  62. eName: fType.Name,
  63. eValue: rVal.Interface(),
  64. },
  65. )
  66. }
  67. }
  68. return
  69. }