Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom validator #35

Merged
merged 6 commits into from
Oct 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,38 @@ type Options struct {
}
```

### Custom validator

You can override `options-gen` validator for specific struct by implementing the `Validator()` method:
```go
import "github.com/mycoolmodule/internal/validator"

// ...

func (Options) Validator() *validator.Validate {
return validator.Validator
}
```

Or you can override `options-gen` validator globally:
```go
package validator

import (
goplvalidator "github.com/go-playground/validator/v10"
optsValidator "github.com/kazhuravlev/options-gen/pkg/validator"
)

var Validator = goplvalidator.New()

func init() {
must(Validator.RegisterValidation(/* ... */))
must(Validator.RegisterAlias(/* ... */))

optsValidator.Set(Validator)
}
```

## Contributing

The development process is pretty simple:
Expand Down
1 change: 1 addition & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ tasks:
dir: examples/library
cmds:
- go run main.go
- go test .

examples:update:cli:
dir: examples/cli
Expand Down
12 changes: 5 additions & 7 deletions examples/cli/options_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions examples/library/example_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ type Options struct {
type Config struct {
name string
}

type Params struct {
hash string `option:"mandatory" validate:"hexadecimal"`
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 37 additions & 0 deletions examples/library/example_out_params.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 25 additions & 16 deletions examples/library/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,30 @@ import (
)

func main() {
if err := optionsgen.Run(
"./example_in.go",
"./example_out.go",
"Options",
"main",
); err != nil {
panic(err)
}

if err := optionsgen.Run(
"./example_in.go",
"./example_out_config.go",
"Config",
"main",
); err != nil {
panic(err)
for _, params := range []struct {
outFname string
structName string
}{
{
outFname: "./example_out_options.go",
structName: "Options",
},
{
outFname: "./example_out_config.go",
structName: "Config",
},
{
outFname: "./example_out_params.go",
structName: "Params",
},
} {
if err := optionsgen.Run(
"./example_in.go",
params.outFname,
params.structName,
"main",
); err != nil {
panic(err)
}
}
}
9 changes: 9 additions & 0 deletions examples/library/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package main

import "testing"

func TestMultiFile(t *testing.T) {
_ = NewOptions(nil, "s3")
_ = NewConfig()
_ = NewParams("d285afedd3e14589ddfe2d6bf4319bfd")
}
15 changes: 5 additions & 10 deletions internal/generator/templates/options.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@
package {{ .packageName }}

import (
"fmt"
fmt461e464ebed9 "fmt"
errors461e464ebed9 "github.com/kazhuravlev/options-gen/pkg/errors"
goplvalidator "github.com/go-playground/validator/v10"
{{ if .hasValidation }}validator461e464ebed9 "github.com/kazhuravlev/options-gen/pkg/validator"{{ end }}
{{- range $import := .imports }}
{{ $import -}}
{{- end }}
)

{{ if .hasValidation }}
var _validator461e464ebed9 = goplvalidator.New()
{{- end }}

type Opt{{ $.optionsStructName }}Setter{{ $.optionsTypeParamsSpec }} func(o *{{ .optionsStructInstanceType }})

func New{{ .optionsStructType }}(
Expand Down Expand Up @@ -45,15 +41,14 @@ func New{{ .optionsStructType }}(
{{ end }}
{{ end }}


func (o *{{ .optionsStructInstanceType }}) Validate() error {
{{- if not .hasValidation -}}
return nil
{{- else }}
errs := new(errors461e464ebed9.ValidationErrors)
{{- range .options }}
{{- if .TagOption.GoValidator }}
errs.Add(errors461e464ebed9.NewValidationError("{{ .Name }}", _validate_{{ $.optionsStructName }}_{{ .Field }}{{ $.optionsTypeParams }}(o)))
errs.Add(errors461e464ebed9.NewValidationError("{{ .Field }}", _validate_{{ $.optionsStructName }}_{{ .Field }}{{ $.optionsTypeParams }}(o)))
{{- end }}
{{- end }}
return errs.AsError()
Expand All @@ -63,8 +58,8 @@ func (o *{{ .optionsStructInstanceType }}) Validate() error {
{{ range .options }}
{{- if .TagOption.GoValidator }}
func _validate_{{ $.optionsStructName }}_{{ .Field }}{{ $.optionsTypeParamsSpec }}(o *{{ $.optionsStructInstanceType }}) error {
if err := _validator461e464ebed9.Var(o.{{ .Field }}, "{{ .TagOption.GoValidator }}"); err != nil {
return fmt.Errorf("field `{{ .Field }}` did not pass the test: %w", err)
if err := validator461e464ebed9.GetValidatorFor(o).Var(o.{{ .Field }}, "{{ .TagOption.GoValidator }}"); err != nil {
return fmt461e464ebed9.Errorf("field `{{ .Field }}` did not pass the test: %w", err)
}
return nil
}
Expand Down
20 changes: 20 additions & 0 deletions options-gen/custom_validator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package optionsgen_test

import (
"testing"

testcase "github.com/kazhuravlev/options-gen/options-gen/testdata/case-09-custom-validator"
"github.com/stretchr/testify/assert"
)

func TestOptionsWithCustomValidator(t *testing.T) {
t.Run("valid options", func(t *testing.T) {
opts := testcase.NewOptions(100, 19)
assert.NoError(t, opts.Validate())
})

t.Run("invalid options", func(t *testing.T) {
opts := testcase.NewOptions(100, 17)
assert.Error(t, opts.Validate())
})
}
32 changes: 32 additions & 0 deletions options-gen/global_override_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package optionsgen_test

import (
"testing"

goplvalidator "github.com/go-playground/validator/v10"
testcase "github.com/kazhuravlev/options-gen/options-gen/testdata/case-10-global-override"
"github.com/kazhuravlev/options-gen/pkg/validator"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestOptionsWithOverridenValidator(t *testing.T) {
v := goplvalidator.New()
require.NoError(t, v.RegisterValidation("child", func(fl goplvalidator.FieldLevel) bool {
return fl.Field().Int() < 14
}))

old := validator.GetValidatorFor(nil)
validator.Set(v)
t.Cleanup(func() { validator.Set(old) })

t.Run("valid options", func(t *testing.T) {
opts := testcase.NewOptions(100, 13)
assert.NoError(t, opts.Validate())
})

t.Run("invalid options", func(t *testing.T) {
opts := testcase.NewOptions(100, 14)
assert.Error(t, opts.Validate())
})
}
Loading