1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 06:20:54 +00:00

Support Match validate function for tag

This commit is contained in:
miraclesu 2013-07-28 19:22:09 +08:00
parent dcdfaf36f1
commit 6662eef2fd
4 changed files with 67 additions and 18 deletions

View File

@ -55,9 +55,10 @@ Struct Tag Use:
// validation function follow with "valid" tag // validation function follow with "valid" tag
// functions divide with ";" // functions divide with ";"
// parameters in parentheses "()" and divide with "," // parameters in parentheses "()" and divide with ","
// Match function's pattern string must in "//"
type user struct { type user struct {
Id int Id int
Name string `valid:"Required"` Name string `valid:"Required;Match(/^(test)?\\w*@;com$/)"`
Age int `valid:"Required;Range(1, 140)"` Age int `valid:"Required;Range(1, 140)"`
} }
@ -86,8 +87,7 @@ Struct Tag Functions:
Alpha Alpha
Numeric Numeric
AlphaNumeric AlphaNumeric
Match(regexp string) // does not support yet Match(pattern string)
NoMatch(regexp string) // does not support yet
AlphaDash AlphaDash
Email Email
IP IP

View File

@ -26,6 +26,7 @@ var (
"apply": true, "apply": true,
"Check": true, "Check": true,
"Valid": true, "Valid": true,
"NoMatch": true,
} }
) )
@ -50,7 +51,7 @@ type Funcs map[string]reflect.Value
func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) { func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
err = r.(error) err = fmt.Errorf("%v", r)
} }
}() }()
if _, ok := f[name]; !ok { if _, ok := f[name]; !ok {
@ -82,10 +83,17 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) {
if len(tag) == 0 { if len(tag) == 0 {
return return
} }
if vfs, tag, err = getRegFuncs(tag, f.Name); err != nil {
fmt.Printf("%+v\n", err)
return
}
fs := strings.Split(tag, ";") fs := strings.Split(tag, ";")
for _, vfunc := range fs { for _, vfunc := range fs {
var vf ValidFunc var vf ValidFunc
vf, err = parseFunc(vfunc) if len(vfunc) == 0 {
continue
}
vf, err = parseFunc(vfunc, f.Name)
if err != nil { if err != nil {
return return
} }
@ -94,10 +102,33 @@ func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) {
return return
} }
func parseFunc(vfunc string) (v ValidFunc, err error) { // Get Match function
// May be get NoMatch function in the future
func getRegFuncs(tag, key string) (vfs []ValidFunc, str string, err error) {
tag = strings.TrimSpace(tag)
index := strings.Index(tag, "Match(/")
if index == -1 {
str = tag
return
}
end := strings.LastIndex(tag, "/)")
if end < index {
err = fmt.Errorf("invalid Match function")
return
}
reg, err := regexp.Compile(tag[index+len("Match(/") : end])
if err != nil {
return
}
vfs = []ValidFunc{ValidFunc{"Match", []interface{}{reg, key}}}
str = strings.TrimSpace(tag[:index]) + strings.TrimSpace(tag[end+len("/)"):])
return
}
func parseFunc(vfunc, key string) (v ValidFunc, err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
err = r.(error) err = fmt.Errorf("%v", r)
} }
}() }()
@ -114,7 +145,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
err = fmt.Errorf("%s require %d parameters", vfunc, num) err = fmt.Errorf("%s require %d parameters", vfunc, num)
return return
} }
v = ValidFunc{vfunc, []interface{}{vfunc}} v = ValidFunc{vfunc, []interface{}{key}}
return return
} }
@ -136,7 +167,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
return return
} }
tParams, err := trim(name, params) tParams, err := trim(name, key, params)
if err != nil { if err != nil {
return return
} }
@ -155,7 +186,7 @@ func numIn(name string) (num int, err error) {
return return
} }
func trim(name string, s []string) (ts []interface{}, err error) { func trim(name, key string, s []string) (ts []interface{}, err error) {
ts = make([]interface{}, len(s), len(s)+1) ts = make([]interface{}, len(s), len(s)+1)
fn, ok := funcs[name] fn, ok := funcs[name]
if !ok { if !ok {
@ -170,7 +201,7 @@ func trim(name string, s []string) (ts []interface{}, err error) {
} }
ts[i] = param ts[i] = param
} }
ts = append(ts, name) ts = append(ts, key)
return return
} }

View File

@ -8,8 +8,9 @@ import (
type user struct { type user struct {
Id int Id int
Tag string `valid:"Maxx(aa)"` Tag string `valid:"Maxx(aa)"`
Name string `valid:"Required"` Name string `valid:"Required;"`
Age int `valid:"Required;Range(1, 140)"` Age int `valid:"Required;Range(1, 140)"`
match string `valid:"Required; Match(/^(test)?\\w*@(/test/);com$/);Max(2)"`
} }
func TestGetValidFuncs(t *testing.T) { func TestGetValidFuncs(t *testing.T) {
@ -55,6 +56,14 @@ func TestGetValidFuncs(t *testing.T) {
if vfs[1].Name != "Range" && len(vfs[1].Params) != 2 { if vfs[1].Name != "Range" && len(vfs[1].Params) != 2 {
t.Error("Range funcs should be got") t.Error("Range funcs should be got")
} }
f, _ = tf.FieldByName("match")
if vfs, err = getValidFuncs(f); err != nil {
t.Fatal(err)
}
if len(vfs) != 3 {
t.Fatal("should get 3 ValidFunc but now is", len(vfs))
}
} }
func TestCall(t *testing.T) { func TestCall(t *testing.T) {

View File

@ -283,12 +283,12 @@ func TestZipCode(t *testing.T) {
func TestValid(t *testing.T) { func TestValid(t *testing.T) {
type user struct { type user struct {
Id int Id int
Name string `valid:"Required"` Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
Age int `valid:"Required;Range(1, 140)"` Age int `valid:"Required;Range(1, 140)"`
} }
valid := Validation{} valid := Validation{}
u := user{Name: "test", Age: 40} u := user{Name: "test@/test/;com", Age: 40}
b, err := valid.Valid(u) b, err := valid.Valid(u)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -297,7 +297,7 @@ func TestValid(t *testing.T) {
t.Error("validation should be passed") t.Error("validation should be passed")
} }
uptr := &user{Name: "test", Age: 180} uptr := &user{Name: "test", Age: 40}
b, err = valid.Valid(uptr) b, err = valid.Valid(uptr)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -305,4 +305,13 @@ func TestValid(t *testing.T) {
if b { if b {
t.Error("validation should not be passed") t.Error("validation should not be passed")
} }
u = user{Name: "test@/test/;com", Age: 180}
b, err = valid.Valid(u)
if err != nil {
t.Fatal(err)
}
if b {
t.Error("validation should not be passed")
}
} }