From 1541305022b679b4610a62ad14161c31da0fc993 Mon Sep 17 00:00:00 2001 From: tamsin johnson Date: Fri, 2 Feb 2024 21:24:04 -0800 Subject: [PATCH] lets-go:8.5 validation helpers --- snippetbox/cmd/web/handlers.go | 25 ++++-------- snippetbox/internal/validator/validator.go | 47 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 snippetbox/internal/validator/validator.go diff --git a/snippetbox/cmd/web/handlers.go b/snippetbox/cmd/web/handlers.go index 5b0039d..6e5176d 100644 --- a/snippetbox/cmd/web/handlers.go +++ b/snippetbox/cmd/web/handlers.go @@ -5,11 +5,10 @@ import ( "fmt" "net/http" "strconv" - "strings" - "unicode/utf8" "github.com/julienschmidt/httprouter" "snippetbox.chaosfem.tw/internal/models" + "snippetbox.chaosfem.tw/internal/validator" ) // home ... @@ -67,7 +66,7 @@ type snippetCreateForm struct { Title string Content string Expires int - FieldErrors map[string]string + validator.Validator } // snippetCreatePost ... @@ -88,24 +87,14 @@ func (app *application) snippetCreatePost(w http.ResponseWriter, r *http.Request Title: r.PostForm.Get("title"), Content: r.PostForm.Get("content"), Expires: expires, - FieldErrors: map[string]string{}, } - if strings.TrimSpace(form.Title) == "" { - form.FieldErrors["title"] = "This field cannot be blank" - } else if utf8.RuneCountInString(form.Title) > 100 { - form.FieldErrors["title"] = "This field cannot contain more than 100 characters" - } + form.CheckField(validator.NotBlank(form.Title), "title", "This field cannot be blank") + form.CheckField(validator.MaxChars(form.Title, 100), "title", "This field cannot be more than 100 characters long") + form.CheckField(validator.NotBlank(form.Content), "content", "This field cannot be blank") + form.CheckField(validator.PermittedValue(form.Expires, 1, 7, 365), "expires", "This field must equal 1, 7 or 365") - if strings.TrimSpace(form.Content) == "" { - form.FieldErrors["content"] = "This field cannot be blank" - } - - if form.Expires != 1 && form.Expires != 7 && form.Expires != 365 { - form.FieldErrors["expires"] = "This field must equal 1, 7 or 365" - } - - if len(form.FieldErrors) > 0 { + if !form.Valid() { data := app.newTemplateData(r) data.Form = form app.render(w, r, http.StatusUnprocessableEntity, "create.tmpl", data) diff --git a/snippetbox/internal/validator/validator.go b/snippetbox/internal/validator/validator.go new file mode 100644 index 0000000..aebe156 --- /dev/null +++ b/snippetbox/internal/validator/validator.go @@ -0,0 +1,47 @@ +package validator + +import ( + "slices" + "strings" + "unicode/utf8" +) + +type Validator struct { + FieldErrors map[string]string +} + +// Valid() ... +func (v *Validator) Valid() bool { + return len(v.FieldErrors) == 0 +} + +// AddFieldError ... +func (v *Validator) AddFieldError(key, message string) { + if v.FieldErrors == nil { + v.FieldErrors = make(map[string]string) + } + + if _, exists := v.FieldErrors[key]; !exists { + v.FieldErrors[key] = message + } +} + +// CheckField ... +func (v *Validator) CheckField(ok bool, key, message string) { + if !ok { + v.AddFieldError(key, message) + } +} + +func NotBlank(value string) bool { + return strings.TrimSpace(value) != "" +} + +func MaxChars(value string, n int) bool { + return utf8.RuneCountInString(value) <= n +} + +// PermittedValue[T comparable] ... +func PermittedValue[T comparable](value T, permittedValues ...T) bool { + return slices.Contains(permittedValues, value) +}