2022-04-05 11:40:53 +02:00
|
|
|
package entity
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Values is a shortcut for map[string]interface{}
|
|
|
|
type Values map[string]interface{}
|
|
|
|
|
|
|
|
// ModelValues extracts Values from an entity model.
|
2022-09-28 09:01:17 +02:00
|
|
|
func ModelValues(m interface{}, omit ...string) (result Values, omitted []interface{}, err error) {
|
|
|
|
mustOmit := func(name string) bool {
|
|
|
|
for _, s := range omit {
|
2022-04-05 11:40:53 +02:00
|
|
|
if name == s {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
r := reflect.ValueOf(m)
|
|
|
|
|
|
|
|
if r.Kind() != reflect.Pointer {
|
2022-09-28 09:01:17 +02:00
|
|
|
return result, omitted, fmt.Errorf("model interface expected")
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
values := r.Elem()
|
|
|
|
|
|
|
|
if kind := values.Kind(); kind != reflect.Struct {
|
2022-09-28 09:01:17 +02:00
|
|
|
return result, omitted, fmt.Errorf("model expected")
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
t := values.Type()
|
|
|
|
num := t.NumField()
|
|
|
|
|
2022-09-28 09:01:17 +02:00
|
|
|
omitted = make([]interface{}, 0, len(omit))
|
2022-04-05 11:40:53 +02:00
|
|
|
result = make(map[string]interface{}, num)
|
|
|
|
|
|
|
|
// Add exported fields to result.
|
|
|
|
for i := 0; i < num; i++ {
|
|
|
|
field := t.Field(i)
|
|
|
|
|
|
|
|
// Skip non-exported fields.
|
|
|
|
if !field.IsExported() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-04-16 12:39:47 +02:00
|
|
|
fieldName := field.Name
|
2022-04-05 11:40:53 +02:00
|
|
|
|
|
|
|
// Skip timestamps.
|
2022-04-16 12:39:47 +02:00
|
|
|
if fieldName == "" || fieldName == "UpdatedAt" || fieldName == "CreatedAt" {
|
2022-04-05 11:40:53 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
v := values.Field(i)
|
|
|
|
|
2022-04-16 12:39:47 +02:00
|
|
|
switch v.Kind() {
|
|
|
|
case reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.UnsafePointer:
|
|
|
|
continue
|
|
|
|
case reflect.Struct:
|
|
|
|
if v.IsZero() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-05 11:40:53 +02:00
|
|
|
// Skip read-only fields.
|
|
|
|
if !v.CanSet() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-09-28 09:01:17 +02:00
|
|
|
// Skip omitted.
|
|
|
|
if mustOmit(fieldName) {
|
2022-04-05 11:40:53 +02:00
|
|
|
if !v.IsZero() {
|
2022-09-28 09:01:17 +02:00
|
|
|
omitted = append(omitted, v.Interface())
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add value to result.
|
2022-04-16 12:39:47 +02:00
|
|
|
result[fieldName] = v.Interface()
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(result) == 0 {
|
2022-09-28 09:01:17 +02:00
|
|
|
return result, omitted, fmt.Errorf("no values")
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|
|
|
|
|
2022-09-28 09:01:17 +02:00
|
|
|
return result, omitted, nil
|
2022-04-05 11:40:53 +02:00
|
|
|
}
|