entc/gen: restructure hooks execution (#741)

Closed #739
This commit is contained in:
Ariel Mashraki
2020-09-09 10:41:17 +03:00
committed by GitHub
parent 3a2c897143
commit b4b4fa95d7
136 changed files with 2248 additions and 1081 deletions

View File

@@ -34,14 +34,17 @@ type {{ $builder }} struct {
// Save creates the {{ $.Name }} in the database.
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (*{{ $.Name }}, error) {
if err := {{ $receiver }}.preSave(); err != nil {
return nil, err
}
var (
err error
node *{{ $.Name }}
)
{{- if $.HasDefault }}
{{ $receiver }}.defaults()
{{- end }}
if len({{ $receiver }}.hooks) == 0 {
if err = {{ $receiver }}.check(); err != nil {
return nil, err
}
node, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
@@ -49,6 +52,9 @@ func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (*{{ $.Name }},
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
if err = {{ $receiver }}.check(); err != nil {
return nil, err
}
{{ $mutation }} = mutation
node, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
mutation.done = true
@@ -73,17 +79,27 @@ func ({{ $receiver }} *{{ $builder }}) SaveX(ctx context.Context) *{{ $.Name }}
return v
}
func ({{ $receiver }} *{{ $builder }}) preSave() error {
{{- $fields := $.Fields }}{{ if $.ID.UserDefined }}{{ $fields = append $fields $.ID }}{{ end }}
{{- range $f := $fields }}
{{- if or $f.Default (and (not $f.Optional) (ne $f.Name $.ID.Name)) }}
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {
{{- if $f.Default }}
{{- $fields := $.Fields }}{{ if $.ID.UserDefined }}{{ $fields = append $fields $.ID }}{{ end }}
{{ if $.HasDefault }}
// defaults sets the default values of the builder before save.
func ({{ $receiver }} *{{ $builder }}) defaults() {
{{- range $f := $fields }}
{{- if or $f.Default }}
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {
v := {{ $.Package }}.{{ $f.DefaultName }}{{ if or $f.IsTime $f.IsUUID }}(){{ end }}
{{ $mutation }}.Set{{ $f.StructField }}(v)
{{- else }}
return &ValidationError{Name: "{{ $f.Name }}", err: errors.New("{{ $pkg }}: missing required field \"{{ $f.Name }}\"")}
{{- end }}
}
{{- end }}
{{- end }}
}
{{ end }}
// check runs all checks and user-defined validators on the builder.
func ({{ $receiver }} *{{ $builder }}) check() error {
{{- range $f := $fields }}
{{- if and (not $f.Optional) (ne $f.Name $.ID.Name) }}
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {
return &ValidationError{Name: "{{ $f.Name }}", err: errors.New("{{ $pkg }}: missing required field \"{{ $f.Name }}\"")}
}
{{- end }}
{{- with or $f.Validators $f.IsEnum }}

View File

@@ -45,14 +45,19 @@ func ({{ $receiver}} *{{ $builder }}) Where(ps ...predicate.{{ $.Name }}) *{{ $b
// Save executes the query and returns the number of rows/vertices matched by this operation.
func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (int, error) {
{{ with extend $ "Receiver" $receiver "Package" $pkg "ZeroValue" 0 -}}
{{ template "update/save" . }}
{{- end -}}
var (
err error
affected int
)
{{- if $.HasUpdateDefault }}
{{ $receiver }}.defaults()
{{- end }}
if len({{ $receiver }}.hooks) == 0 {
{{- if $.HasUpdateCheckers }}
if err = {{ $receiver }}.check(); err != nil {
return 0, err
}
{{- end }}
affected, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
@@ -60,6 +65,11 @@ func ({{ $receiver }} *{{ $builder }}) Save(ctx context.Context) (int, error) {
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
{{- if $.HasUpdateCheckers }}
if err = {{ $receiver }}.check(); err != nil {
return 0, err
}
{{- end }}
{{ $mutation }} = mutation
affected, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
mutation.done = true
@@ -97,6 +107,10 @@ func ({{ $receiver }} *{{ $builder }}) ExecX(ctx context.Context) {
}
}
{{ with extend $ "Receiver" $receiver "Package" $pkg "Builder" $builder }}
{{ template "update/checks" . }}
{{ end }}
{{ with extend $ "Builder" $builder "Package" $pkg }}
{{ $tmpl := printf "dialect/%s/update" $.Storage }}
{{ xtemplate $tmpl . }}
@@ -123,14 +137,19 @@ type {{ $onebuilder }} struct {
// Save executes the query and returns the updated entity.
func ({{ $receiver }} *{{ $onebuilder }} ) Save(ctx context.Context) (*{{ $.Name }}, error) {
{{ with extend $ "Receiver" $receiver "Package" $pkg "ZeroValue" "nil" -}}
{{ template "update/save" . }}
{{- end -}}
var (
err error
node *{{ $.Name }}
)
{{- if $.HasUpdateDefault }}
{{ $receiver }}.defaults()
{{- end }}
if len({{ $receiver }}.hooks) == 0 {
{{- if $.HasUpdateCheckers }}
if err = {{ $receiver }}.check(); err != nil {
return nil, err
}
{{- end }}
node, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
} else {
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
@@ -138,6 +157,11 @@ func ({{ $receiver }} *{{ $onebuilder }} ) Save(ctx context.Context) (*{{ $.Name
if !ok {
return nil, fmt.Errorf("unexpected mutation type %T", m)
}
{{- if $.HasUpdateCheckers }}
if err = {{ $receiver }}.check(); err != nil {
return nil, err
}
{{- end }}
{{ $mutation }} = mutation
node, err = {{ $receiver }}.{{ $.Storage }}Save(ctx)
mutation.done = true
@@ -175,6 +199,10 @@ func ({{ $receiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
}
}
{{ with extend $ "Receiver" $receiver "Package" $pkg "Builder" $onebuilder }}
{{ template "update/checks" . }}
{{ end }}
{{ with extend $ "Builder" $onebuilder "Package" $pkg }}
{{ $tmpl := printf "dialect/%s/update" $.Storage }}
{{ xtemplate $tmpl . }}
@@ -225,34 +253,49 @@ func ({{ $receiver }} *{{ $onebuilder }}) ExecX(ctx context.Context) {
{{ end }}
{{ end }}
{{/* shared template for the save method of the 2 builders */}}
{{ define "update/save" }}
{{- $pkg := .Scope.Package -}}
{{- $zero := .Scope.ZeroValue }}
{{- $receiver := .Scope.Receiver -}}
{{- $mutation := print $receiver ".mutation" -}}
{{/* shared template for the 2 update builders */}}
{{ define "update/checks" }}
{{ $pkg := .Scope.Package }}
{{ $receiver := .Scope.Receiver }}
{{ $builder := pascal .Scope.Builder }}
{{ $mutation := print $receiver ".mutation" }}
{{- range $_, $f := $.Fields -}}
{{- if $f.UpdateDefault -}}
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {{ if $f.Optional }} && !{{ $mutation }}.{{ $f.StructField }}Cleared() {{ end }} {
v := {{ $.Package }}.{{ $f.UpdateDefaultName }}{{ if $f.IsTime }}(){{ end }}
{{ $mutation }}.Set{{ $f.StructField }}(v)
}
{{ end -}}
{{ with and (or $f.Validators $f.IsEnum) (not $f.Immutable) -}}
if v, ok := {{ $mutation }}.{{ $f.MutationGet }}(); ok {
{{- $basic := $f.BasicType "v" }}
if err := {{ $.Package }}.{{ $f.Validator }}({{ $basic }}); err != nil {
return {{ $zero }}, &ValidationError{Name: "{{ $f.Name }}", err: fmt.Errorf("{{ $pkg }}: validator failed for field \"{{ $f.Name }}\": %w", err)}
}
}
{{ end -}}
{{ end -}}
{{- range $_, $e := $.Edges }}
{{ if and $e.Unique (not $e.Optional) -}}
if _, ok := {{ $mutation }}.{{ $e.StructField }}ID(); {{ $mutation }}.{{ $e.StructField }}Cleared() && !ok {
return {{ $zero }}, errors.New("{{ $pkg }}: clearing a unique edge \"{{ $e.Name }}\"")
}
{{ end -}}
{{ end -}}
{{ if $.HasUpdateDefault }}
// defaults sets the default values of the builder before save.
func ({{ $receiver }} *{{ $builder }}) defaults() {
{{- range $f := $.Fields }}
{{- if $f.UpdateDefault }}
if _, ok := {{ $mutation }}.{{ $f.MutationGet }}(); !ok {{ if $f.Optional }} && !{{ $mutation }}.{{ $f.StructField }}Cleared() {{ end }} {
v := {{ $.Package }}.{{ $f.UpdateDefaultName }}{{ if $f.IsTime }}(){{ end }}
{{ $mutation }}.Set{{ $f.StructField }}(v)
}
{{- end }}
{{- end }}
}
{{ end }}
{{ if $.HasUpdateCheckers }}
// check runs all checks and user-defined validators on the builder.
func ({{ $receiver }} *{{ $builder }}) check() error {
{{- range $f := $.Fields }}
{{- with and (or $f.Validators $f.IsEnum) (not $f.Immutable) }}
if v, ok := {{ $mutation }}.{{ $f.MutationGet }}(); ok {
{{- $basic := $f.BasicType "v" }}
if err := {{ $.Package }}.{{ $f.Validator }}({{ $basic }}); err != nil {
return &ValidationError{Name: "{{ $f.Name }}", err: fmt.Errorf("{{ $pkg }}: validator failed for field \"{{ $f.Name }}\": %w", err)}
}
}
{{- end }}
{{- end }}
{{- range $e := $.Edges }}
{{- if and $e.Unique (not $e.Optional) }}
if _, ok := {{ $mutation }}.{{ $e.StructField }}ID(); {{ $mutation }}.{{ $e.StructField }}Cleared() && !ok {
return errors.New("{{ $pkg }}: clearing a required unique edge \"{{ $e.Name }}\"")
}
{{- end }}
{{- end }}
return nil
}
{{ end }}
{{ end }}