-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathbiz_scope.go
159 lines (141 loc) · 3.7 KB
/
biz_scope.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package kuu
import (
"fmt"
"github.com/jinzhu/gorm"
"reflect"
)
// Scope
type Scope struct {
skipLeft bool
Value interface{}
Meta *Metadata
ReflectType reflect.Type
Context *Context
DB *gorm.DB
callbacks *Callback
QueryResult *BizQueryResult
UpdateCond interface{}
UpdateParams *BizUpdateParams
}
// BizUpdateParams
type BizUpdateParams struct {
All bool
Multi bool
Cond map[string]interface{}
Doc map[string]interface{}
}
// BizQueryResult
type BizQueryResult struct {
Cond map[string]interface{} `json:"cond,omitempty"`
Project string `json:"project,omitempty"`
Preload string `json:"preload,omitempty"`
Sort string `json:"sort,omitempty"`
Range string `json:"range,omitempty"`
Page int `json:"page,omitempty"`
Size int `json:"size,omitempty"`
TotalRecords int `json:"totalrecords,omitempty"`
TotalPages int `json:"totalpages,omitempty"`
List interface{} `json:"list,omitempty"`
}
type BizPreloadInterface interface {
BizPreloadHandlers() map[string]func(*gorm.DB) *gorm.DB
}
// NewBizScope
func NewBizScope(c *Context, value interface{}, db *gorm.DB) *Scope {
reflectType := reflect.ValueOf(value).Type()
for reflectType.Kind() == reflect.Slice || reflectType.Kind() == reflect.Ptr {
reflectType = reflectType.Elem()
}
scope := &Scope{
Context: c,
DB: db,
Value: value,
Meta: Meta(value),
callbacks: DefaultCallback,
ReflectType: reflectType,
}
return scope
}
// IndirectValue
func (scope *Scope) IndirectValue() reflect.Value {
return indirectValue(scope.Value)
}
// SkipLeft skip remaining callbacks
func (scope *Scope) SkipLeft() {
scope.skipLeft = true
}
// Err
func (scope *Scope) Err(err error) error {
return scope.DB.AddError(err)
}
// HasError
func (scope *Scope) HasError() bool {
return scope.DB.Error != nil
}
// CallMethod
func (scope *Scope) CallMethod(methodName string) {
if scope.Value == nil {
return
}
if indirectScopeValue := scope.IndirectValue(); indirectScopeValue.Kind() == reflect.Slice {
for i := 0; i < indirectScopeValue.Len(); i++ {
scope.callMethod(methodName, indirectScopeValue.Index(i))
}
} else {
scope.callMethod(methodName, indirectScopeValue)
}
}
func (scope *Scope) callCallbacks(kind string) *Scope {
defer func() {
if err := recover(); err != nil {
if scope.DB != nil {
scope.DB.Rollback()
}
panic(err)
}
}()
var funcs []*func(s *Scope)
switch kind {
case BizCreateKind:
funcs = scope.callbacks.creates
case BizQueryKind:
funcs = scope.callbacks.queries
case BizUpdateKind:
funcs = scope.callbacks.updates
case BizDeleteKind:
funcs = scope.callbacks.deletes
}
for _, f := range funcs {
(*f)(scope)
if scope.skipLeft {
break
}
}
return scope
}
func (scope *Scope) callMethod(methodName string, reflectValue reflect.Value) {
// Only get address from non-pointer
if reflectValue.CanAddr() && reflectValue.Kind() != reflect.Ptr {
reflectValue = reflectValue.Addr()
}
if methodValue := reflectValue.MethodByName(methodName); methodValue.IsValid() {
switch method := methodValue.Interface().(type) {
case func():
method()
case func(*Scope):
method(scope)
case func(*gorm.DB):
method(scope.DB)
case func(*gorm.DB) *gorm.DB:
scope.DB = method(scope.DB)
case func() error:
_ = scope.Err(method())
case func(*Scope) error:
_ = scope.Err(method(scope))
case func(*gorm.DB) error:
_ = scope.Err(method(scope.DB))
default:
_ = scope.Err(fmt.Errorf("unsupported function %v", methodName))
}
}
}