entc/gen: introduce validation errors (#547)

This introduces the concept of validation errors, where we have a high
level validation error which wraps a more detailed error message.

The higher level `ValidationError` is set up in the generated files, much
like the `NotFoundError` and `ConstraintError` and is accompanied by an
`IsValidationError` check method. Thus, it can be used as follows:

```go
t, err := tx.Team.Create().SetName(input.Name).Save(ctx)
if ent.IsValidationError(err) {
        // handle validation error response
}
```
This commit is contained in:
Jelmer Snoeck
2020-06-17 11:11:39 -03:00
committed by GitHub
parent c616f7f2e7
commit b150cde478
143 changed files with 846 additions and 246 deletions

View File

@@ -64,10 +64,10 @@ func (cc *CarCreate) Mutation() *CarMutation {
// Save creates the Car in the database.
func (cc *CarCreate) Save(ctx context.Context) (*Car, error) {
if _, ok := cc.mutation.Model(); !ok {
return nil, errors.New("ent: missing required field \"model\"")
return nil, &ValidationError{Name: "model", err: errors.New("ent: missing required field \"model\"")}
}
if _, ok := cc.mutation.RegisteredAt(); !ok {
return nil, errors.New("ent: missing required field \"registered_at\"")
return nil, &ValidationError{Name: "registered_at", err: errors.New("ent: missing required field \"registered_at\"")}
}
var (
err error

View File

@@ -319,7 +319,7 @@ func (cuo *CarUpdateOne) sqlSave(ctx context.Context) (c *Car, err error) {
}
id, ok := cuo.mutation.ID()
if !ok {
return nil, fmt.Errorf("missing Car.ID for update")
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Car.ID for update")}
}
_spec.Node.ID.Value = id
if value, ok := cuo.mutation.Model(); ok {

View File

@@ -100,6 +100,31 @@ func Sum(field string) AggregateFunc {
}
}
// ValidationError returns when validating a field fails.
type ValidationError struct {
Name string // Field or edge name.
err error
}
// Error implements the error interface.
func (e *ValidationError) Error() string {
return e.err.Error()
}
// Unwrap implements the errors.Wrapper interface.
func (e *ValidationError) Unwrap() error {
return e.err
}
// IsValidationError returns a boolean indicating whether the error is a validaton error.
func IsValidationError(err error) bool {
if err == nil {
return false
}
var e *ValidationError
return errors.As(err, &e)
}
// NotFoundError returns when trying to fetch a specific entity and it was not found in the database.
type NotFoundError struct {
label string

View File

@@ -53,11 +53,11 @@ func (gc *GroupCreate) Mutation() *GroupMutation {
// Save creates the Group in the database.
func (gc *GroupCreate) Save(ctx context.Context) (*Group, error) {
if _, ok := gc.mutation.Name(); !ok {
return nil, errors.New("ent: missing required field \"name\"")
return nil, &ValidationError{Name: "name", err: errors.New("ent: missing required field \"name\"")}
}
if v, ok := gc.mutation.Name(); ok {
if err := group.NameValidator(v); err != nil {
return nil, fmt.Errorf("ent: validator failed for field \"name\": %w", err)
return nil, &ValidationError{Name: "name", err: fmt.Errorf("ent: validator failed for field \"name\": %w", err)}
}
}
var (

View File

@@ -77,7 +77,7 @@ func (gu *GroupUpdate) RemoveUsers(u ...*User) *GroupUpdate {
func (gu *GroupUpdate) Save(ctx context.Context) (int, error) {
if v, ok := gu.mutation.Name(); ok {
if err := group.NameValidator(v); err != nil {
return 0, fmt.Errorf("ent: validator failed for field \"name\": %w", err)
return 0, &ValidationError{Name: "name", err: fmt.Errorf("ent: validator failed for field \"name\": %w", err)}
}
}
@@ -256,7 +256,7 @@ func (guo *GroupUpdateOne) RemoveUsers(u ...*User) *GroupUpdateOne {
func (guo *GroupUpdateOne) Save(ctx context.Context) (*Group, error) {
if v, ok := guo.mutation.Name(); ok {
if err := group.NameValidator(v); err != nil {
return nil, fmt.Errorf("ent: validator failed for field \"name\": %w", err)
return nil, &ValidationError{Name: "name", err: fmt.Errorf("ent: validator failed for field \"name\": %w", err)}
}
}
@@ -322,7 +322,7 @@ func (guo *GroupUpdateOne) sqlSave(ctx context.Context) (gr *Group, err error) {
}
id, ok := guo.mutation.ID()
if !ok {
return nil, fmt.Errorf("missing Group.ID for update")
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing Group.ID for update")}
}
_spec.Node.ID.Value = id
if value, ok := guo.mutation.Name(); ok {

View File

@@ -83,11 +83,11 @@ func (uc *UserCreate) Mutation() *UserMutation {
// Save creates the User in the database.
func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
if _, ok := uc.mutation.Age(); !ok {
return nil, errors.New("ent: missing required field \"age\"")
return nil, &ValidationError{Name: "age", err: errors.New("ent: missing required field \"age\"")}
}
if v, ok := uc.mutation.Age(); ok {
if err := user.AgeValidator(v); err != nil {
return nil, fmt.Errorf("ent: validator failed for field \"age\": %w", err)
return nil, &ValidationError{Name: "age", err: fmt.Errorf("ent: validator failed for field \"age\": %w", err)}
}
}
if _, ok := uc.mutation.Name(); !ok {

View File

@@ -129,7 +129,7 @@ func (uu *UserUpdate) RemoveGroups(g ...*Group) *UserUpdate {
func (uu *UserUpdate) Save(ctx context.Context) (int, error) {
if v, ok := uu.mutation.Age(); ok {
if err := user.AgeValidator(v); err != nil {
return 0, fmt.Errorf("ent: validator failed for field \"age\": %w", err)
return 0, &ValidationError{Name: "age", err: fmt.Errorf("ent: validator failed for field \"age\": %w", err)}
}
}
@@ -411,7 +411,7 @@ func (uuo *UserUpdateOne) RemoveGroups(g ...*Group) *UserUpdateOne {
func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) {
if v, ok := uuo.mutation.Age(); ok {
if err := user.AgeValidator(v); err != nil {
return nil, fmt.Errorf("ent: validator failed for field \"age\": %w", err)
return nil, &ValidationError{Name: "age", err: fmt.Errorf("ent: validator failed for field \"age\": %w", err)}
}
}
@@ -477,7 +477,7 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (u *User, err error) {
}
id, ok := uuo.mutation.ID()
if !ok {
return nil, fmt.Errorf("missing User.ID for update")
return nil, &ValidationError{Name: "ID", err: fmt.Errorf("missing User.ID for update")}
}
_spec.Node.ID.Value = id
if value, ok := uuo.mutation.Age(); ok {