Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom rule method added #98

Merged
merged 1 commit into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion after.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) After(t, u time.Time, field, msg string) Validator {
v.Check(t.After(u), field, v.msg(After, msg, field, u))
v.check(t.After(u), field, v.msg(After, msg, field, u))

return v
}
2 changes: 1 addition & 1 deletion before.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) Before(t, u time.Time, field, msg string) Validator {
v.Check(t.Before(u), field, v.msg(Before, msg, field, u))
v.check(t.Before(u), field, v.msg(Before, msg, field, u))

return v
}
4 changes: 2 additions & 2 deletions between.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) BetweenInt(i, min, max int, field, msg string) Validator {
v.Check(i >= min && i <= max, field, v.msg(Between, msg, field, min, max))
v.check(i >= min && i <= max, field, v.msg(Between, msg, field, min, max))

return v
}
Expand All @@ -32,7 +32,7 @@ func (v Validator) BetweenInt(i, min, max int, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) BetweenFloat(f, min, max float64, field, msg string) Validator {
v.Check(f >= min && f <= max, field, v.msg(Between, msg, field, min, max))
v.check(f >= min && f <= max, field, v.msg(Between, msg, field, min, max))

return v
}
11 changes: 11 additions & 0 deletions custom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package govalidator

// CustomRule is a dynamic method to define any custom validation rule by passing a rule as a function or expression
// which will return a boolean.
func (v Validator) CustomRule(ok bool, field, msg string) Validator {
if !ok {
v.addError(field, msg)
}

return v
}
70 changes: 70 additions & 0 deletions custom_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package govalidator

import (
"github.com/stretchr/testify/assert"
"testing"
)

func Test_CustomRule(t *testing.T) {
tests := []struct {
name string
field string
value bool
isPassed bool
msg string
expectedMsg string
}{
{
name: "test CustomRule with true condition",
value: true,
field: "username",
msg: "",
isPassed: true,
expectedMsg: "",
},
{
name: "test CustomRule with false condition and custom message",
value: false,
field: "username",
msg: "username must be unique",
isPassed: false,
expectedMsg: "username must be unique",
},
{
name: "test CustomRule with false condition and empty message",
value: false,
field: "email",
msg: "",
isPassed: false,
expectedMsg: "",
},
{
name: "test CustomRule with true condition and custom message",
value: true,
field: "email",
msg: "email must be valid",
isPassed: true,
expectedMsg: "",
},
}

for _, test := range tests {
v := New()

v.CustomRule(test.value, test.field, test.msg)

assert.Equal(t, test.isPassed, v.IsPassed(), test.name)

if !test.isPassed {
assert.Equalf(
t,
test.expectedMsg,
v.Errors()[test.field],
"test case %q failed, expected: %s, got: %s",
test.name,
test.expectedMsg,
v.Errors()[test.field],
)
}
}
}
2 changes: 1 addition & 1 deletion date.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
func (v Validator) Date(layout, d, field, msg string) Validator {
_, err := time.Parse(layout, d)
if err != nil {
v.Check(false, field, v.msg(Date, msg, field))
v.check(false, field, v.msg(Date, msg, field))
}

return v
Expand Down
2 changes: 1 addition & 1 deletion exists.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) Exists(value any, table, column, field, msg string) Validator {
v.Check(v.repo.Exists(value, table, column), field, v.msg(Exists, msg, field))
v.check(v.repo.Exists(value, table, column), field, v.msg(Exists, msg, field))

return v
}
15 changes: 15 additions & 0 deletions exists_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ func (repo) Exists(value any, table, column string) bool {
return false
}

func (repo) ExistsExceptSelf(value any, table, column string, selfID int) bool {
data, exists := tables[table]
if !exists {
return false
}

for _, item := range data {
if item[column] == value {
return true
}
}

return false
}

func TestValidator_Exists(t *testing.T) {
tests := []struct {
name string
Expand Down
2 changes: 1 addition & 1 deletion ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
func (v Validator) IP4(s, field, msg string) Validator {
ip := net.ParseIP(s)

v.Check(ip != nil && ip.To4() != nil, field, v.msg(IP4, msg, field))
v.check(ip != nil && ip.To4() != nil, field, v.msg(IP4, msg, field))

return v
}
6 changes: 3 additions & 3 deletions len.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) LenString(s string, size int, field, msg string) Validator {
v.Check(utf8.RuneCountInString(strings.TrimSpace(s)) == size, field, v.msg(Len, msg, field, size))
v.check(utf8.RuneCountInString(strings.TrimSpace(s)) == size, field, v.msg(Len, msg, field, size))

return v
}
Expand All @@ -42,7 +42,7 @@ func (v Validator) LenString(s string, size int, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) LenInt(i, size int, field, msg string) Validator {
v.Check(len(strconv.Itoa(i)) == size, field, v.msg(Len, msg, field, size))
v.check(len(strconv.Itoa(i)) == size, field, v.msg(Len, msg, field, size))

return v
}
Expand All @@ -57,7 +57,7 @@ func (v Validator) LenInt(i, size int, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) LenSlice(s []any, size int, field, msg string) Validator {
v.Check(len(s) == size, field, v.msg(LenList, msg, field, size))
v.check(len(s) == size, field, v.msg(LenList, msg, field, size))

return v
}
6 changes: 3 additions & 3 deletions max.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MaxInt(i, max int, field, msg string) Validator {
v.Check(i <= max, field, v.msg(Max, msg, field, max))
v.check(i <= max, field, v.msg(Max, msg, field, max))

return v
}
Expand All @@ -41,7 +41,7 @@ func (v Validator) MaxInt(i, max int, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MaxFloat(f, max float64, field, msg string) Validator {
v.Check(f <= max, field, v.msg(Max, msg, field, max))
v.check(f <= max, field, v.msg(Max, msg, field, max))

return v
}
Expand All @@ -56,7 +56,7 @@ func (v Validator) MaxFloat(f, max float64, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MaxString(s string, maxLen int, field, msg string) Validator {
v.Check(utf8.RuneCountInString(strings.TrimSpace(s)) <= maxLen, field, v.msg(MaxString, msg, field, maxLen))
v.check(utf8.RuneCountInString(strings.TrimSpace(s)) <= maxLen, field, v.msg(MaxString, msg, field, maxLen))

return v
}
6 changes: 3 additions & 3 deletions min.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MinInt(i, min int, field, msg string) Validator {
v.Check(i >= min, field, v.msg(Min, msg, field, min))
v.check(i >= min, field, v.msg(Min, msg, field, min))

return v
}
Expand All @@ -41,7 +41,7 @@ func (v Validator) MinInt(i, min int, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MinFloat(f, min float64, field, msg string) Validator {
v.Check(f >= min, field, v.msg(Min, msg, field, min))
v.check(f >= min, field, v.msg(Min, msg, field, min))

return v
}
Expand All @@ -56,7 +56,7 @@ func (v Validator) MinFloat(f, min float64, field, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) MinString(s string, minLen int, field, msg string) Validator {
v.Check(utf8.RuneCountInString(strings.TrimSpace(s)) >= minLen, field, v.msg(MinString, msg, field, minLen))
v.check(utf8.RuneCountInString(strings.TrimSpace(s)) >= minLen, field, v.msg(MinString, msg, field, minLen))

return v
}
2 changes: 1 addition & 1 deletion notexists.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) NotExists(value any, table, column, field, msg string) Validator {
v.Check(!v.repo.Exists(value, table, column), field, v.msg(NotExists, msg, field))
v.check(!v.repo.Exists(value, table, column), field, v.msg(NotExists, msg, field))

return v
}
2 changes: 1 addition & 1 deletion regex.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
func (v Validator) RegexMatches(s string, pattern string, field, msg string) Validator {
r := regexp.MustCompile(pattern)

v.Check(r.Match([]byte(s)), field, v.msg(Regex, msg))
v.check(r.Match([]byte(s)), field, v.msg(Regex, msg))

return v
}
8 changes: 4 additions & 4 deletions required.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const (
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) RequiredString(s, field string, msg string) Validator {
v.Check(strings.TrimSpace(s) != "", field, v.msg(Required, msg, field))
v.check(strings.TrimSpace(s) != "", field, v.msg(Required, msg, field))

return v
}
Expand All @@ -34,7 +34,7 @@ func (v Validator) RequiredString(s, field string, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) RequiredInt(i int, field string, msg string) Validator {
v.Check(i != 0, field, v.msg(Required, msg, field))
v.check(i != 0, field, v.msg(Required, msg, field))

return v
}
Expand All @@ -49,7 +49,7 @@ func (v Validator) RequiredInt(i int, field string, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) RequiredSlice(s []any, field string, msg string) Validator {
v.Check(len(s) > 0, field, v.msg(Required, msg, field))
v.check(len(s) > 0, field, v.msg(Required, msg, field))

return v
}
Expand All @@ -64,7 +64,7 @@ func (v Validator) RequiredSlice(s []any, field string, msg string) Validator {
// fmt.Printf("validation errors: %#v\n", v.Errors())
// }
func (v Validator) RequiredFloat(f float64, field string, msg string) Validator {
v.Check(f != 0.0, field, v.msg(Required, msg, field))
v.check(f != 0.0, field, v.msg(Required, msg, field))

return v
}
2 changes: 1 addition & 1 deletion url.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
func (v Validator) URL(s, field, msg string) Validator {
u, err := url.Parse(s)

v.Check(err == nil && u.Scheme != "" && u.Host != "", field, v.msg(URL, msg, field))
v.check(err == nil && u.Scheme != "" && u.Host != "", field, v.msg(URL, msg, field))

return v
}
2 changes: 1 addition & 1 deletion uuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
func (v Validator) UUID(u, field, msg string) Validator {
_, err := uuid.Parse(u)
if err != nil {
v.Check(false, field, v.msg(UUID, msg, field))
v.check(false, field, v.msg(UUID, msg, field))

return v
}
Expand Down
6 changes: 3 additions & 3 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type (
// check a record exists on database or not.
Repository interface {
Exists(value any, table, column string) bool
ExistsExceptSelf(value any, table, column string, selfID int) bool
}

// Validator represents the validator structure
Expand Down Expand Up @@ -80,9 +81,8 @@ func (v Validator) Errors() map[string]string {
return v.errs
}

// Check is a dynamic method to define any custom validator rule by passing a rule as a function or expression
// which will return a boolean.
func (v Validator) Check(ok bool, field, msg string) {
// check is the internal method easily validate each validator method result
func (v Validator) check(ok bool, field, msg string) {
if !ok {
v.addError(field, msg)
}
Expand Down
Loading