278f8eb1 by slene

add ValidFormer interface, can custom valid

1 parent 658a671b
...@@ -7,6 +7,10 @@ import ( ...@@ -7,6 +7,10 @@ import (
7 "strings" 7 "strings"
8 ) 8 )
9 9
10 type ValidFormer interface {
11 Valid(*Validation)
12 }
13
10 type ValidationError struct { 14 type ValidationError struct {
11 Message, Key, Name, Field, Tmpl string 15 Message, Key, Name, Field, Tmpl string
12 Value interface{} 16 Value interface{}
...@@ -21,9 +25,35 @@ func (e *ValidationError) String() string { ...@@ -21,9 +25,35 @@ func (e *ValidationError) String() string {
21 return e.Message 25 return e.Message
22 } 26 }
23 27
28 // A ValidationResult is returned from every validation method.
29 // It provides an indication of success, and a pointer to the Error (if any).
30 type ValidationResult struct {
31 Error *ValidationError
32 Ok bool
33 }
34
35 func (r *ValidationResult) Key(key string) *ValidationResult {
36 if r.Error != nil {
37 r.Error.Key = key
38 }
39 return r
40 }
41
42 func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
43 if r.Error != nil {
44 if len(args) == 0 {
45 r.Error.Message = message
46 } else {
47 r.Error.Message = fmt.Sprintf(message, args...)
48 }
49 }
50 return r
51 }
52
24 // A Validation context manages data validation and error messages. 53 // A Validation context manages data validation and error messages.
25 type Validation struct { 54 type Validation struct {
26 Errors []*ValidationError 55 Errors []*ValidationError
56 ErrorsMap map[string]*ValidationError
27 } 57 }
28 58
29 func (v *Validation) Clear() { 59 func (v *Validation) Clear() {
...@@ -38,13 +68,7 @@ func (v *Validation) HasErrors() bool { ...@@ -38,13 +68,7 @@ func (v *Validation) HasErrors() bool {
38 // If there are multiple validation errors associated with a single key, the 68 // If there are multiple validation errors associated with a single key, the
39 // first one "wins". (Typically the first validation will be the more basic). 69 // first one "wins". (Typically the first validation will be the more basic).
40 func (v *Validation) ErrorMap() map[string]*ValidationError { 70 func (v *Validation) ErrorMap() map[string]*ValidationError {
41 m := map[string]*ValidationError{} 71 return v.ErrorsMap
42 for _, e := range v.Errors {
43 if _, ok := m[e.Key]; !ok {
44 m[e.Key] = e
45 }
46 }
47 return m
48 } 72 }
49 73
50 // Add an error to the validation context. 74 // Add an error to the validation context.
...@@ -57,31 +81,6 @@ func (v *Validation) Error(message string, args ...interface{}) *ValidationResul ...@@ -57,31 +81,6 @@ func (v *Validation) Error(message string, args ...interface{}) *ValidationResul
57 return result 81 return result
58 } 82 }
59 83
60 // A ValidationResult is returned from every validation method.
61 // It provides an indication of success, and a pointer to the Error (if any).
62 type ValidationResult struct {
63 Error *ValidationError
64 Ok bool
65 }
66
67 func (r *ValidationResult) Key(key string) *ValidationResult {
68 if r.Error != nil {
69 r.Error.Key = key
70 }
71 return r
72 }
73
74 func (r *ValidationResult) Message(message string, args ...interface{}) *ValidationResult {
75 if r.Error != nil {
76 if len(args) == 0 {
77 r.Error.Message = message
78 } else {
79 r.Error.Message = fmt.Sprintf(message, args...)
80 }
81 }
82 return r
83 }
84
85 // Test that the argument is non-nil and non-empty (if string or list) 84 // Test that the argument is non-nil and non-empty (if string or list)
86 func (v *Validation) Required(obj interface{}, key string) *ValidationResult { 85 func (v *Validation) Required(obj interface{}, key string) *ValidationResult {
87 return v.apply(Required{key}, obj) 86 return v.apply(Required{key}, obj)
...@@ -192,7 +191,7 @@ func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult { ...@@ -192,7 +191,7 @@ func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
192 Tmpl: MessageTmpls[Name], 191 Tmpl: MessageTmpls[Name],
193 LimitValue: chk.GetLimitValue(), 192 LimitValue: chk.GetLimitValue(),
194 } 193 }
195 v.Errors = append(v.Errors, err) 194 v.setError(err)
196 195
197 // Also return it in the result. 196 // Also return it in the result.
198 return &ValidationResult{ 197 return &ValidationResult{
...@@ -201,6 +200,22 @@ func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult { ...@@ -201,6 +200,22 @@ func (v *Validation) apply(chk Validator, obj interface{}) *ValidationResult {
201 } 200 }
202 } 201 }
203 202
203 func (v *Validation) setError(err *ValidationError) {
204 v.Errors = append(v.Errors, err)
205 if v.ErrorsMap == nil {
206 v.ErrorsMap = make(map[string]*ValidationError)
207 }
208 if _, ok := v.ErrorsMap[err.Field]; !ok {
209 v.ErrorsMap[err.Field] = err
210 }
211 }
212
213 func (v *Validation) SetError(fieldName string, errMsg string) *ValidationError {
214 err := &ValidationError{Key: fieldName, Field: fieldName, Tmpl: errMsg, Message: errMsg}
215 v.setError(err)
216 return err
217 }
218
204 // Apply a group of validators to a field, in order, and return the 219 // Apply a group of validators to a field, in order, and return the
205 // ValidationResult from the first one that fails, or the last one that 220 // ValidationResult from the first one that fails, or the last one that
206 // succeeds. 221 // succeeds.
...@@ -241,5 +256,12 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) { ...@@ -241,5 +256,12 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) {
241 } 256 }
242 } 257 }
243 } 258 }
259
260 if !v.HasErrors() {
261 if form, ok := obj.(ValidFormer); ok {
262 form.Valid(v)
263 }
264 }
265
244 return !v.HasErrors(), nil 266 return !v.HasErrors(), nil
245 } 267 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!