Skip to content

Commit 79afaeb

Browse files
committed
Validation: add WithMessage
1 parent c111c05 commit 79afaeb

File tree

14 files changed

+70
-16
lines changed

14 files changed

+70
-16
lines changed

lang/lang_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ func (suite *LangTestSuite) TestLoad() {
9797
},
9898
validation: validationLines{
9999
rules: map[string]string{
100-
"override": "rule override",
101-
"required.array": "The :field values are required.",
100+
"override": "rule override",
101+
"required.array": "The :field values are required.",
102+
"messageOverride": "Custom error message: placeholders work: ':field', :min - :max",
102103
},
103104
fields: map[string]string{
104105
"email": "email address",

middleware_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,8 @@ func TestLanguageMiddleware(t *testing.T) {
245245
}
246246

247247
type testValidator struct {
248-
validation.BaseValidator
249248
validateFunc func(c *testValidator, ctx *validation.Context) bool
249+
validation.BaseValidator
250250
}
251251

252252
func (v *testValidator) Validate(ctx *validation.Context) bool {

resources/lang/en-US/rules.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"override": "rule override",
3-
"required.array": "The :field values are required."
3+
"required.array": "The :field values are required.",
4+
"messageOverride": "Custom error message: placeholders work: ':field', :min - :max"
45
}

validation/comparison.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import (
1616
// - Compare the number of keys in an object with a numeric field
1717
// - Compare a file (or multifile) size with a numeric field. The number of KiB of each file is rounded up (ceil).
1818
type ComparisonValidator struct {
19-
BaseValidator
2019
Path *walk.Path
20+
BaseValidator
2121
}
2222

2323
// Validate checks the field under validation satisfies this validator's criteria.

validation/date.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ func Date(acceptedFormats ...string) *DateValidator {
6262

6363
// DateComparisonValidator factorized date comparison validator for static dates (before, after, etc.)
6464
type DateComparisonValidator struct {
65-
BaseValidator
6665
Date time.Time
66+
BaseValidator
6767
}
6868

6969
func (v *DateComparisonValidator) validate(ctx *Context, comparisonFunc func(time.Time, time.Time) bool) bool {
@@ -85,8 +85,8 @@ func (v *DateComparisonValidator) MessagePlaceholders(_ *Context) []string {
8585

8686
// DateFieldComparisonValidator factorized date comparison validator for field dates (before field, after field, etc.)
8787
type DateFieldComparisonValidator struct {
88-
BaseValidator
8988
Path *walk.Path
89+
BaseValidator
9090
}
9191

9292
func (v *DateFieldComparisonValidator) validate(ctx *Context, comparisonFunc func(time.Time, time.Time) bool) bool {

validation/different.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import (
1414
// For numbers, make sure the two compared numbers have the same type. A `uint` with value `1` will be considered
1515
// different from an `int` with value `1`.
1616
type DifferentValidator struct {
17-
BaseValidator
1817
Path *walk.Path
18+
BaseValidator
1919
}
2020

2121
// Validate checks the field under validation satisfies this validator's criteria.

validation/in.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ func NotIn[T comparable](values []T) *NotInValidator[T] {
8383
// InFieldValidator validates the field under validation must be in at least one
8484
// of the arrays matched by the specified path.
8585
type InFieldValidator[T comparable] struct {
86-
BaseValidator
8786
Path *walk.Path
87+
BaseValidator
8888
}
8989

9090
// Validate checks the field under validation satisfies this validator's criteria.

validation/regex.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import "regexp"
55
// RegexValidator the field under validation must be a string matching
66
// the specified `*regexp.Regexp`.
77
type RegexValidator struct {
8-
BaseValidator
98
Regexp *regexp.Regexp
9+
BaseValidator
1010
}
1111

1212
// Validate checks the field under validation satisfies this validator's criteria.

validation/required.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ func Required() *RequiredValidator {
3636
// RequiredIfValidator is the same as `RequiredValidator` but only applies the behavior
3737
// described if the specified `Condition` function returns true.
3838
type RequiredIfValidator struct {
39-
RequiredValidator
4039
Condition func(*Context) bool
40+
RequiredValidator
4141
}
4242

4343
// Validate checks the field under validation satisfies this validator's criteria.

validation/ruleset.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,16 @@ type Validator interface {
5555
// This is use to generate the validation error message. An empty slice can be returned.
5656
// See `lang.Language.Get()` for more details.
5757
MessagePlaceholders(ctx *Context) []string
58+
59+
overrideMessage(langEntry string)
60+
getMessageOverride() string
5861
}
5962

6063
// BaseValidator composable structure that implements the basic functions required to
6164
// satisfy the `Validator` interface.
6265
type BaseValidator struct {
6366
component
67+
messageOverride string
6468
}
6569

6670
func (v *BaseValidator) init(options *Options) {
@@ -86,6 +90,22 @@ func (v *BaseValidator) IsType() bool { return false }
8690
// MessagePlaceholders returns an empty slice (no placeholders)
8791
func (v *BaseValidator) MessagePlaceholders(_ *Context) []string { return []string{} }
8892

93+
func (v *BaseValidator) overrideMessage(langEntry string) {
94+
v.messageOverride = langEntry
95+
}
96+
97+
func (v *BaseValidator) getMessageOverride() string {
98+
return v.messageOverride
99+
}
100+
101+
// WithMessage set a custom language entry for the error message of a Validator.
102+
// Original placeholders returned by the validator are still used to render the message.
103+
// Type-dependent and "element" suffixes are not added when the message is overridden.
104+
func WithMessage[V Validator](v V, langEntry string) V {
105+
v.overrideMessage(langEntry)
106+
return v
107+
}
108+
89109
// FieldRulesConverter types implementing this interface define their behavior
90110
// when converting a `FieldRules` to `Rules`. This enables rule sets composition.
91111
type FieldRulesConverter interface {

0 commit comments

Comments
 (0)