Skip to content

Commit

Permalink
Add documentation, update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
BrandonRomano committed Jun 22, 2017
1 parent 54352a9 commit 8009ad9
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 19 deletions.
59 changes: 53 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,28 @@ Let's check out the Value struct.

```go
type Value struct {
Result interface{}
Name string
Input string
Rules []Rule
Result interface{}
Default string
Name string
Input string
Rules []Rule
TypeHandler TypeHandler
}
```

#### Result

Result must be a pointer to the variable you want to store the parsed input in.

Valid types for this are `*string`, `*float32`, `*float64`, `*bool`, `*int`, `*int8`, `*int16`, `*int32`, `*int64`, `*uint`, `*uint8`, `*uint16`, `*uint32`, `*uint64`.
By default, supported types for this are `*string`, `*float32`, `*float64`, `*bool`, `*int`, `*int8`, `*int16`, `*int32`, `*int64`, `*uint`, `*uint8`, `*uint16`, `*uint32`, `*uint64`.

It is expected that the value of the `Input` parameter can be parsed into the decided type using their respective [strconv](https://golang.org/pkg/strconv/) function, else an error will be thrown by [the Validate function](#the-validate-function) when it is called.
For the default supported types, it is expected that the value of the `Input` parameter can be parsed into the decided type using their respective [strconv](https://golang.org/pkg/strconv/) function, else an error will be thrown by [the Validate function](#the-validate-function) when it is called.

If you need to use another type, `TypeHandler` must also be set to the Value struct.

#### Default

This is the optional default value of `Input` that will be set, if the value of `Input` ends up being an empty string.

#### Name

Expand All @@ -70,6 +78,12 @@ This is a slice of rules that you require a particular value to pass.

This is optional, and can be not set if you don't have any rules for your value to pass. The value will still go through the type check if the Input is a non-empty string.

#### TypeHandler

TypeHandler is a function that defines how the input string is parsed.

For basic types, it's not necessary to implement your own TypeHandler, as they have already been implemented and will be attached to Values automatically.

## Rules

A Rule is a very simple type of function:
Expand Down Expand Up @@ -113,6 +127,39 @@ Both of these strategies should feel very fluent in use:

> You won't find any prebuilt rules in [go-carrot/validator](https://github.com/go-carrot/validator). If you're looking for those check out the [go-carrot/rules](https://github.com/go-carrot/rules) repository.
## TypeHandlers

A TypeHandler is a function that follows the following definition:

```go
type TypeHandler func(input string, value *Value) error
```

A TypeHandler is responsible for:

- Validation of the non-null string input
- (TypeHandlers aren't called if the string is not set - you can mandate that a value is required via `Rules`)
- Converting string input to the desired type
- Passing the converted type into the `value.Result`

TypeHandlers are best explained by example. This is a TypeHandler for a `*sql.NullInt64`

```go
func NullInt64TypeHandler = func(input string, value *v.Value) error {
// Get int64
res, err := strconv.ParseInt(input, 10, 64)
if err != nil {
return errors.New("Invalid parameter, must be an int64")
}

// Update nullInt
nullInt := value.Result.(*sql.NullInt64)
(*nullInt).Int64 = int64(res)
(*nullInt).Valid = true
return nil
}
```

## The Validate Function

The validate function is the function that will actually perform your input validation. This function will throw an error if any of your values fail validation.
Expand Down
42 changes: 29 additions & 13 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -655,28 +655,44 @@ func TestUint64(t *testing.T) {
// and use it as expected
func TestCustomTypeHandler(t *testing.T) {
// Create type handler
var nullStringTypeHandler = func(input string, value *v.Value) error {
nullString := value.Result.(*sql.NullString)
(*nullString).String = input
(*nullString).Valid = (input != "")
var nullInt64TypeHandler = func(input string, value *v.Value) error {
// Get int64
res, err := strconv.ParseInt(input, 10, 64)
if err != nil {
return errors.New("Invalid parameter, must be an int64")
}

// Update nullInt
nullInt := value.Result.(*sql.NullInt64)
(*nullInt).Int64 = int64(res)
(*nullInt).Valid = true
return nil
}

// Test valid case
var slug sql.NullString
var id sql.NullInt64
err := v.Validate([]*v.Value{
{Result: &slug, Name: "slug", Input: "wow", TypeHandler: nullStringTypeHandler},
{Result: &id, Name: "id", Input: "42", TypeHandler: nullInt64TypeHandler},
})
assert.Nil(t, err)
assert.Equal(t, "wow", slug.String)
assert.Equal(t, true, slug.Valid)
assert.Equal(t, int64(42), id.Int64)
assert.Equal(t, true, id.Valid)

// Test invalid case
var emptySlug sql.NullString
// Test empty case
var emptyId sql.NullInt64
err = v.Validate([]*v.Value{
{Result: &emptySlug, Name: "slug", Input: "", TypeHandler: nullStringTypeHandler},
{Result: &emptyId, Name: "id", Input: "", TypeHandler: nullInt64TypeHandler},
})
assert.Nil(t, err)
assert.Equal(t, "", emptySlug.String)
assert.Equal(t, false, emptySlug.Valid)
assert.Equal(t, int64(0), emptyId.Int64)
assert.Equal(t, false, emptyId.Valid)

// Test error case
var errorId sql.NullInt64
err = v.Validate([]*v.Value{
{Result: &errorId, Name: "id", Input: "abcd", TypeHandler: nullInt64TypeHandler},
})
assert.NotNil(t, err)
assert.Equal(t, int64(0), errorId.Int64)
assert.Equal(t, false, errorId.Valid)
}

0 comments on commit 8009ad9

Please sign in to comment.