Passed
Push — main ( 36e3e5...da04d5 )
by Rushan
01:11 queued 10s
created

lidateString   A

Complexity

Conditions 5

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
dl 0
loc 24
rs 9.3333
c 0
b 0
f 0
nop 2
1
package validation_test
2
3
import (
4
	"context"
5
	"errors"
6
	"fmt"
7
8
	"github.com/muonsoft/validation"
9
	"github.com/muonsoft/validation/it"
10
	"github.com/muonsoft/validation/validator"
11
)
12
13
type contextKey string
14
15
const exampleKey contextKey = "exampleKey"
16
17
type TagStorage struct {
18
	// this might be stored in the database
19
	tags []string
20
}
21
22
func (storage *TagStorage) FindByName(ctx context.Context, name string) ([]string, error) {
23
	contextValue, ok := ctx.Value(exampleKey).(string)
24
	if !ok {
25
		return nil, errors.New("context value missing")
26
	}
27
	if contextValue != "value" {
28
		return nil, errors.New("invalid context value")
29
	}
30
31
	found := make([]string, 0)
32
33
	for _, tag := range storage.tags {
34
		if tag == name {
35
			found = append(found, tag)
36
		}
37
	}
38
39
	return found, nil
40
}
41
42
type ExistingTagConstraint struct {
43
	storage *TagStorage
44
}
45
46
func (c *ExistingTagConstraint) SetUp() error {
47
	return nil
48
}
49
50
func (c *ExistingTagConstraint) Name() string {
51
	return "ExistingTagConstraint"
52
}
53
54
func (c *ExistingTagConstraint) ValidateString(value *string, scope validation.Scope) error {
55
	// usually, you should ignore empty values
56
	// to check for an empty value you should use it.NotBlankConstraint
57
	if value == nil || *value == "" {
58
		return nil
59
	}
60
61
	// you can pass the context value from the scope
62
	entities, err := c.storage.FindByName(scope.Context(), *value)
63
	// here you can return a service error so that the validation process
64
	// is stopped immediately
65
	if err != nil {
66
		return err
67
	}
68
	if len(entities) > 0 {
69
		return nil
70
	}
71
72
	// use the scope to build violation with translations
73
	return scope.
74
		BuildViolation("unknownTag", `Tag "{{ value }}" does not exist.`).
75
		// you can inject parameter value to the message here
76
		AddParameter("{{ value }}", *value).
77
		CreateViolation()
78
}
79
80
func ExampleValidator_Validate_customServiceConstraint() {
81
	storage := &TagStorage{tags: []string{"camera", "book"}}
82
	isTagExists := &ExistingTagConstraint{storage: storage}
83
84
	tag := "movie"
85
	ctx := context.WithValue(context.Background(), exampleKey, "value")
86
87
	err := validator.Validate(
88
		// you can pass here the context value to the validation scope
89
		validation.Context(ctx),
90
		validation.String(&tag, it.IsNotBlank(), isTagExists),
91
	)
92
93
	violations := err.(validation.ViolationList)
94
	for _, violation := range violations {
95
		fmt.Println(violation.Error())
96
	}
97
	// Output:
98
	// violation: Tag "movie" does not exist.
99
}
100