github.com/duskeagle/pop@v4.10.1-0.20190417200916-92f2b794aab5+incompatible/validations.go (about) 1 package pop 2 3 import ( 4 "reflect" 5 6 "github.com/gobuffalo/validate" 7 "github.com/pkg/errors" 8 ) 9 10 type beforeValidatable interface { 11 BeforeValidations(*Connection) error 12 } 13 14 type validateable interface { 15 Validate(*Connection) (*validate.Errors, error) 16 } 17 18 type modelIterableValidator func(*Model) (*validate.Errors, error) 19 20 func (m *Model) validate(c *Connection) (*validate.Errors, error) { 21 if x, ok := m.Value.(beforeValidatable); ok { 22 if err := x.BeforeValidations(c); err != nil { 23 return validate.NewErrors(), errors.WithStack(err) 24 } 25 } 26 if x, ok := m.Value.(validateable); ok { 27 return x.Validate(c) 28 } 29 return validate.NewErrors(), nil 30 } 31 32 type validateCreateable interface { 33 ValidateCreate(*Connection) (*validate.Errors, error) 34 } 35 36 func (m *Model) validateCreate(c *Connection) (*validate.Errors, error) { 37 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 38 verrs, err := model.validate(c) 39 if err != nil { 40 return verrs, errors.WithStack(err) 41 } 42 if x, ok := model.Value.(validateCreateable); ok { 43 vs, err := x.ValidateCreate(c) 44 if vs != nil { 45 verrs.Append(vs) 46 } 47 if err != nil { 48 return verrs, errors.WithStack(err) 49 } 50 } 51 52 return verrs, err 53 }) 54 } 55 56 func (m *Model) validateAndOnlyCreate(c *Connection) (*validate.Errors, error) { 57 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 58 id, err := model.fieldByName("ID") 59 if err != nil { 60 return nil, err 61 } 62 if !IsZeroOfUnderlyingType(id.Interface()) { 63 return validate.NewErrors(), nil 64 } 65 66 verrs, err := model.validate(c) 67 if err != nil { 68 return verrs, errors.WithStack(err) 69 } 70 if x, ok := model.Value.(validateCreateable); ok { 71 vs, err := x.ValidateCreate(c) 72 if vs != nil { 73 verrs.Append(vs) 74 } 75 if err != nil { 76 return verrs, errors.WithStack(err) 77 } 78 } 79 80 return verrs, err 81 }) 82 } 83 84 type validateSaveable interface { 85 ValidateSave(*Connection) (*validate.Errors, error) 86 } 87 88 func (m *Model) validateSave(c *Connection) (*validate.Errors, error) { 89 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 90 verrs, err := model.validate(c) 91 if err != nil { 92 return verrs, errors.WithStack(err) 93 } 94 if x, ok := model.Value.(validateSaveable); ok { 95 vs, err := x.ValidateSave(c) 96 if vs != nil { 97 verrs.Append(vs) 98 } 99 if err != nil { 100 return verrs, errors.WithStack(err) 101 } 102 } 103 104 return verrs, err 105 }) 106 } 107 108 type validateUpdateable interface { 109 ValidateUpdate(*Connection) (*validate.Errors, error) 110 } 111 112 func (m *Model) validateUpdate(c *Connection) (*validate.Errors, error) { 113 return m.iterateAndValidate(func(model *Model) (*validate.Errors, error) { 114 verrs, err := model.validate(c) 115 if err != nil { 116 return verrs, errors.WithStack(err) 117 } 118 if x, ok := model.Value.(validateUpdateable); ok { 119 vs, err := x.ValidateUpdate(c) 120 if vs != nil { 121 verrs.Append(vs) 122 } 123 if err != nil { 124 return verrs, errors.WithStack(err) 125 } 126 } 127 128 return verrs, err 129 }) 130 } 131 132 func (m *Model) iterateAndValidate(fn modelIterableValidator) (*validate.Errors, error) { 133 v := reflect.Indirect(reflect.ValueOf(m.Value)) 134 if v.Kind() == reflect.Slice || v.Kind() == reflect.Array { 135 for i := 0; i < v.Len(); i++ { 136 val := v.Index(i) 137 newModel := &Model{Value: val.Addr().Interface()} 138 verrs, err := fn(newModel) 139 140 if err != nil || verrs.HasAny() { 141 return verrs, err 142 } 143 } 144 return validate.NewErrors(), nil 145 } 146 147 return fn(m) 148 }