From f93aff9808c366e2083778c2a3b7ee473b4f537b Mon Sep 17 00:00:00 2001 From: Reza Khademi Date: Thu, 30 May 2024 11:51:47 +0330 Subject: [PATCH] feat: better readme docs --- CHANGELOG.md | 4 ++ README.md | 116 +++++++++++++++++++++++++++++++++------------------ validator.go | 25 +++++++++++ 3 files changed, 105 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19312d6..75fb795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## v2.0.6 (2024-05-30) + +- History of changes: see https://github.com/rezakhademix/govalidator/compare/v2.0.5...v2.0.6 + ## v2.0.5 (2024-05-08) - History of changes: see https://github.com/rezakhademix/govalidator/compare/v2.0.4...v2.0.5 diff --git a/README.md b/README.md index e343f2d..0e95598 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Go Reference](https://pkg.go.dev/badge/github.com/rezakhademix/govalidator.svg)](https://pkg.go.dev/github.com/rezakhademix/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/rezakhademix/govalidator)](https://goreportcard.com/report/github.com/rezakhademix/govalidator) [![codecov](https://codecov.io/gh/rezakhademix/govalidator/graph/badge.svg?token=BDWNVIC670)](https://codecov.io/gh/rezakhademix/govalidator) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) +[![Go Reference](https://pkg.go.dev/badge/github.com/rezakhademix/govalidator.svg)](https://pkg.go.dev/github.com/rezakhademix/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/rezakhademix/govalidator)](https://goreportcard.com/report/github.com/rezakhademix/govalidator) [![codecov](https://codecov.io/gh/rezakhademix/govalidator/graph/badge.svg?token=BDWNVIC670)](https://codecov.io/gh/rezakhademix/govalidator) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) # GoValidator GoValidator is a data validation package that can sanitize and validate your data to ensure its safety and integrity as much as possible. GoValidator will not use struct tags as validation and there is no need of them. @@ -27,37 +27,39 @@ Each validation rule in GoValidator has it's own default message, e.g: `required ### Methods (also known as validation rules) --- -| Method | Description | -| -------------- | ----------------------------------------------------------------------------------- | -| RequiredInt | `RequiredInt` checks if an integer value is provided or not. | -| RequiredFloat | `RequiredFloat` checks if a float value is provided or not. | -| RequiredString | `RequiredString` checks if a string value is empty or not. | -| RequiredSlice | `RequiredSlice` checks if a slice has any value or not. | -| BetweenInt | `BetweenInt` checks whether value falls within the specified range or not. | -| BetweenFloat | `BetweenFloat` checks whether value falls within the specified range or not. | -| Date | `Date` checks value to be a valid, non-relative date. | -| Email | `Email` checks value to match `EmailRegex` regular expression. | -| Exists | `Exists` checks given value exists in given table or not. | -| NotExists | `NotExists` checks given value doesn't exist in given table. | -| LenString | `LenString` checks length of given string is equal to given size or not. | -| LenInt | `LenInt` checks length of given integer is equal to given size or not. | -| LenSlice | `LenSlice` checks length of given slice is equal to given size or not. | -| MaxInt | `MaxInt` checks given integer is less than or equal given max value. | -| MaxFloat | `MaxFloat` checks given float is less than or equal given max value. | -| MaxString | `MaxString` checks length of given string is less than or equal given max value. | -| MinInt | `MinInt` checks given integer is greater than or equal given min value. | -| MinFloat | `MinFloat` checks given float is greater than or equal given min value. | -| MinString | `MinString` checks length of given string is greater than or equal given min value. | -| RegexMatches | `RegexMatches` checks given string matches given regular expression pattern. | -| UUID | `UUID` checks given value is a valid universally unique identifier (UUID). | -| When | `When` will execute given closure if given condition is true. | -| URL | `URL` will check given string is a valid URL or not. | -| Before | `Before` will check if given time instant t is before given time instant u. | -| After | `After` will check if given time instant t is after given time instant u. | -| IP4 | `IP4` will check whether given string is a valid IPV4. | -| DefaultInt | `DefaultInt` sets a default value for any pointer to an int that is passed. | -| DefaultFloat | `DefaultFloat` sets a default value for any pointer to a float that is passed. | -| DefaultString | `DefaultString` sets a default value for any pointer to a string that is passed. | +| Method | Description | +|------------------|---------------------------------------------------------------------------------------------------------------------| +| RequiredInt | `RequiredInt` checks if an integer value is provided or not. | +| RequiredFloat | `RequiredFloat` checks if a float value is provided or not. | +| RequiredString | `RequiredString` checks if a string value is empty or not. | +| RequiredSlice | `RequiredSlice` checks if a slice has any value or not. | +| BetweenInt | `BetweenInt` checks whether value falls within the specified range or not. | +| BetweenFloat | `BetweenFloat` checks whether value falls within the specified range or not. | +| Date | `Date` checks value to be a valid, non-relative date. | +| Email | `Email` checks value to match `EmailRegex` regular expression. | +| Exists | `Exists` checks given value exists in given table or not. | +| NotExists | `NotExists` checks given value doesn't exist in given table, except. | +| ExistsExceptSelf | `ExistsExceptSelf` checks given value exists in a specified column of a table, excluding a row identified by selfID | +| LenString | `LenString` checks length of given string is equal to given size or not. | +| LenInt | `LenInt` checks length of given integer is equal to given size or not. | +| LenSlice | `LenSlice` checks length of given slice is equal to given size or not. | +| MaxInt | `MaxInt` checks given integer is less than or equal given max value. | +| MaxFloat | `MaxFloat` checks given float is less than or equal given max value. | +| MaxString | `MaxString` checks length of given string is less than or equal given max value. | +| MinInt | `MinInt` checks given integer is greater than or equal given min value. | +| MinFloat | `MinFloat` checks given float is greater than or equal given min value. | +| MinString | `MinString` checks length of given string is greater than or equal given min value. | +| RegexMatches | `RegexMatches` checks given string matches given regular expression pattern. | +| UUID | `UUID` checks given value is a valid universally unique identifier (UUID). | +| When | `When` will execute given closure if given condition is true. | +| URL | `URL` will check given string is a valid URL or not. | +| Before | `Before` will check if given time instant t is before given time instant u. | +| After | `After` will check if given time instant t is after given time instant u. | +| IP4 | `IP4` will check whether given string is a valid IPV4. | +| DefaultInt | `DefaultInt` sets a default value for any pointer to an int that is passed. | +| DefaultFloat | `DefaultFloat` sets a default value for any pointer to a float that is passed. | +| DefaultString | `DefaultString` sets a default value for any pointer to a string that is passed. | +| CustomRule | `CustomRule` is a dynamic method to define any custom validation rule. | ### Functions (other common validation rules) --- @@ -70,7 +72,7 @@ Each validation rule in GoValidator has it's own default message, e.g: `required --- ### Examples: --- -1. simple: +1. Simple usage: ```go type User struct { Name string `json:"name"` @@ -80,7 +82,7 @@ Each validation rule in GoValidator has it's own default message, e.g: `required var user User _ := c.Bind(&user) // error ignored for simplicity - v := govalidator.New() + v := govalidator.New() // be sure to import govalidator/v2 v.RequiredInt(user.Age, "age", ""). // age can not be null or 0 MinInt(user.Age, 18, "age", "") // minimum value for age is 18 @@ -93,7 +95,7 @@ Each validation rule in GoValidator has it's own default message, e.g: `required } ``` -2. with custom field names and messages: +2. With custom field names and messages: ```go type User struct { Name string `json:"name"` @@ -111,7 +113,7 @@ Each validation rule in GoValidator has it's own default message, e.g: `required } ``` -3. more complex with custom validation rule: You can define any custom rules or any flexible rule that does not exist in default govalidator package. Simply use check() method to define your desired data validations: +3. Advanced usage with any custom validation rule: You can define any custom rules or any flexible rule that does not exist in default govalidator package. Simply use check() method to define your desired data validations: ```go type Profile struct { @@ -127,24 +129,58 @@ Each validation rule in GoValidator has it's own default message, e.g: `required v := govalidator.New() - v.Check(profile.Name != "", "name", "name is required") // check is a method to define rule as first parameter and then pass field name and validation error message + v.CustomRule(profile.Name != "", "name", "name is required") // check is a method to define rule as first parameter and then pass field name and validation error message - v.Check(profile.Age > 18, "age", "age must be greater than 18") + v.CustomRule(profile.Age > 18, "age", "age must be greater than 18") // we just need to pass a bool as a rule // `checkScore()` is your custom method that returns a bool and can be used as a rule - v.Check(checkScore(), "score", "score must") + v.CustomRule(checkScore(), "score", "score must") // using `In` Generic rule: statuses := []string{"active", "inactive", "pending"} - v.Check(validator.In[ProfileStatuses](profile.Status, statuses), "status", "status must be in:...") + v.CustomRule(validator.In[ProfileStatuses](profile.Status, statuses), "status", "status must be in:...") if v.IsFailed() { return v.Errors() } ``` +4. Deep Dive: + + ```go + type CategoryCreateReq struct { + ParentID *int `json:"parent_id"` + Name string `json:"name"` + Description string `json:"description"` + Status int `json:"status"` + } + + + var categoryCreateReq CategoryCreateReq + + // after filling categoryCreateReq struct data with binding or other methods + + v := govalidator.New() // be sure to import govalidator/v2 + + ok := v.RequiredString(req.Name, "name", msgCategoryNameRequired). + MaxString(req.Name, nameMaxLength, "name", msgCategoryNameMaxLength). + MinString(req.Name, nameMinLength, "name", msgCategoryNameMinLength). + NotExists(req.Name, "categories", "name", "name", msgCategoryNameAlreadyExists). // ensure the value of req.Name does not exist in the "name" column of the "categories" table in the database + MaxString(req.Description, descriptionMaxLength, "description", msgdescriptionMaxLength). + MinInt(req.Status, minStatus, "status", msgMinCategoryStatusIsWrong). + MaxInt(req.Status, maxStatus, "status", msgMaxCategoryStatusIsWrong). + When(req.ParentID != nil, func() { + v.Exists(*req.ParentID, "categories", "id", "parent_id", msgCategoryParentIDNotExist) // checks if the value of req.ParentID exists in the "id" column of the "categories" table in the database + }). + IsPassed() + + if !ok { + return v.Errors() + } + ``` + --- ### Benchmarks --- diff --git a/validator.go b/validator.go index 81ebe35..9b5b3bb 100644 --- a/validator.go +++ b/validator.go @@ -10,7 +10,32 @@ type ( // Repository represent a repository for using in rules that needs a database connection to // check a record exists on database or not. Repository interface { + // Exists checks whether a given value exists in a specified column of a table. + // This function is typically used to validate the uniqueness of a value in a database. + // + // Parameters: + // - value: The value to check for existence. + // - table: The name of the table to search within. + // - column: The column to check for the value. + // + // Returns: + // - bool: Returns true if the value exists in the specified column of the table; + // otherwise, returns false. Exists(value any, table, column string) bool + + // ExistsExceptSelf checks whether a given value exists in a specified column of a table, + // excluding a row identified by selfID. This is typically used to ensure the uniqueness + // of a value in a table, while allowing updates to a row without triggering a false positive. + // + // Parameters: + // - value: The value to check for existence. + // - table: The name of the table to search within. + // - column: The column to check for the value. + // - selfID: The ID of the row to exclude from the check. + // + // Returns: + // - bool: Returns true if the value exists in the specified column of the table, excluding + // ExistsExceptSelf(value any, table, column string, selfID int) bool }