Skip to content

Commit

Permalink
Add support for jsonapi in models generator (#434)
Browse files Browse the repository at this point in the history
* Add support for jsonapi in models generator

Replaces #230

Credits to @leodotcloud for the original PR based on the old generator.

* Fix String() for jsonapi models
  • Loading branch information
stanislas-m committed Sep 18, 2019
1 parent fa578ca commit aa19b35
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 10 deletions.
62 changes: 62 additions & 0 deletions genny/model/_fixtures/models/widget_jsonapi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package models

import (
"strings"
"time"

"github.com/gobuffalo/nulls"
"github.com/gobuffalo/pop"
"github.com/gobuffalo/validate"
"github.com/gobuffalo/validate/validators"
"github.com/gofrs/uuid"
"github.com/google/jsonapi"
)

type Widget struct {
ID uuid.UUID `jsonapi:"primary,id" db:"id"`
CreatedAt time.Time `jsonapi:"attr,created_at" db:"created_at"`
UpdatedAt time.Time `jsonapi:"attr,updated_at" db:"updated_at"`
Name string `jsonapi:"attr,name" db:"name"`
Description string `jsonapi:"attr,description" db:"description"`
Age int `jsonapi:"attr,age" db:"age"`
Bar nulls.String `jsonapi:"attr,bar" db:"bar"`
}

// String is not required by pop and may be deleted
func (w Widget) String() string {
var jb strings.Builder
_ = jsonapi.MarshalPayload(&jb, &w)
return jb.String()
}

// Widgets is not required by pop and may be deleted
type Widgets []Widget

// String is not required by pop and may be deleted
func (w Widgets) String() string {
var jb strings.Builder
_ = jsonapi.MarshalPayload(&jb, &w)
return jb.String()
}

// Validate gets run every time you call a "pop.Validate*" (pop.ValidateAndSave, pop.ValidateAndCreate, pop.ValidateAndUpdate) method.
// This method is not required and may be deleted.
func (w *Widget) Validate(tx *pop.Connection) (*validate.Errors, error) {
return validate.Validate(
&validators.StringIsPresent{Field: w.Name, Name: "Name"},
&validators.StringIsPresent{Field: w.Description, Name: "Description"},
&validators.IntIsPresent{Field: w.Age, Name: "Age"},
), nil
}

// ValidateCreate gets run every time you call "pop.ValidateAndCreate" method.
// This method is not required and may be deleted.
func (w *Widget) ValidateCreate(tx *pop.Connection) (*validate.Errors, error) {
return validate.NewErrors(), nil
}

// ValidateUpdate gets run every time you call "pop.ValidateAndUpdate" method.
// This method is not required and may be deleted.
func (w *Widget) ValidateUpdate(tx *pop.Connection) (*validate.Errors, error) {
return validate.NewErrors(), nil
}
7 changes: 6 additions & 1 deletion genny/model/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ func buildImports(opts *Options) []string {
imps := map[string]bool{
"github.com/gobuffalo/validate": true,
}
imps[path.Join("encoding", strings.ToLower(opts.Encoding))] = true
if opts.Encoding == "jsonapi" {
imps["github.com/google/jsonapi"] = true
imps["strings"] = true
} else {
imps[path.Join("encoding", strings.ToLower(opts.Encoding))] = true
}
ats := opts.Attrs
for _, a := range ats {
switch a.GoType() {
Expand Down
46 changes: 44 additions & 2 deletions genny/model/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (

func clean(s string) string {
s = strings.TrimSpace(s)
s = strings.Replace(s, "\n", "", -1)
s = strings.Replace(s, "\r\n", "\n", -1)
s = strings.Replace(s, "\r", "\n", -1)
s = strings.Replace(s, "\t", "", -1)
s = strings.Replace(s, "\r", "", -1)
return s
}

Expand Down Expand Up @@ -150,6 +150,48 @@ func Test_New_XML(t *testing.T) {
r.Equal(clean(bf), clean(f.String()))
}

func Test_New_JSONAPI(t *testing.T) {
r := require.New(t)

ats, err := attrs.ParseArgs("id:uuid", "created_at:timestamp", "updated_at:timestamp", "name", "description:text", "age:int", "bar:nulls.String")
r.NoError(err)
g, err := New(&Options{
Name: "widget",
Encoding: "jsonapi",
Attrs: ats,
})

r.NoError(err)

run := gentest.NewRunner()
run.With(g)

r.NoError(run.Run())

res := run.Results()

r.Len(res.Commands, 0)
r.NoError(gentest.CompareFiles([]string{"models/widget.go", "models/widget_test.go"}, res.Files))

box := packr.New("Test_New_JSONAPI", "../model/_fixtures")

f, err := res.Find("models/widget_test.go")
r.NoError(err)
bf, err := box.FindString(f.Name())
r.NoError(err)
r.Equal(bf, f.String())

f, err = res.Find("models/widget.go")

tf := gogen.FmtTransformer()
f, err = tf.Transform(f)
r.NoError(err)

bf, err = box.FindString("models/widget_jsonapi.go")
r.NoError(err)
r.Equal(clean(bf), clean(f.String()))
}

func Test_New_Package(t *testing.T) {
r := require.New(t)

Expand Down
3 changes: 3 additions & 0 deletions genny/model/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ func (opts *Options) Validate() error {
opts.Encoding = "json"
}
opts.Encoding = strings.ToLower(opts.Encoding)
if opts.Encoding != "json" && opts.Encoding != "jsonapi" && opts.Encoding != "xml" {
return errors.Errorf("unsupported encoding option %s", opts.Encoding)
}

return opts.forceDefaults()
}
Expand Down
21 changes: 20 additions & 1 deletion genny/model/templates/-path-/-name-.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,44 @@ import (
{{- end }}
)

{{- if eq $.model.Encoding.String "jsonapi"}}
type {{.model.Name.Proper}} struct {
{{- range $a := .opts.Attrs }}
{{$a.Name.Pascalize}} {{$a.GoType}} `jsonapi:"{{ if eq $a.Name.Underscore.String "id" }}primary{{ else }}attr{{ end }},{{$a.Name.Underscore}}" db:"{{$a.Name.Underscore}}"`
{{- end }}
{{- else }}
type {{.model.Name.Proper}} struct {
{{- range $a := .opts.Attrs }}
{{$a.Name.Pascalize}} {{$a.GoType}} `{{$.model.Encoding}}:"{{$a.Name.Underscore}}" db:"{{$a.Name.Underscore}}"`
{{- end}}
{{- end }}
{{- end }}
}

// String is not required by pop and may be deleted
func ({{.model.Name.Char}} {{.model.Name.Proper}}) String() string {
{{- if eq $.model.Encoding.String "jsonapi"}}
var jb strings.Builder
_ = jsonapi.MarshalPayload(&jb, &{{.model.Name.Char}})
return jb.String()
{{- else }}
{{.model.Encoding.Char}}{{.model.Name.Char}}, _ := {{.model.Encoding}}.Marshal({{.model.Name.Char}})
return string({{.model.Encoding.Char}}{{.model.Name.Char}})
{{- end }}
}

// {{.model.Name.Proper.Pluralize}} is not required by pop and may be deleted
type {{.model.Name.Proper.Pluralize}} []{{.model.Name.Proper}}

// String is not required by pop and may be deleted
func ({{.model.Name.Char}} {{.model.Name.Proper.Pluralize}}) String() string {
{{- if eq $.model.Encoding.String "jsonapi"}}
var jb strings.Builder
_ = jsonapi.MarshalPayload(&jb, &{{.model.Name.Char}})
return jb.String()
{{- else }}
{{.model.Encoding.Char}}{{.model.Name.Char}}, _ := {{.model.Encoding}}.Marshal({{.model.Name.Char}})
return string({{.model.Encoding.Char}}{{.model.Name.Char}})
{{- end }}
}

// Validate gets run every time you call a "pop.Validate*" (pop.ValidateAndSave, pop.ValidateAndCreate, pop.ValidateAndUpdate) method.
Expand Down
13 changes: 8 additions & 5 deletions packrd/packed-packr.go

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

2 changes: 1 addition & 1 deletion soda/cmd/generate/model_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var modelCmdConfig struct {
}

func init() {
ModelCmd.Flags().StringVarP(&modelCmdConfig.StructTag, "struct-tag", "", "json", "sets the struct tags for model (xml or json)")
ModelCmd.Flags().StringVarP(&modelCmdConfig.StructTag, "struct-tag", "", "json", "sets the struct tags for model (xml/json/jsonapi)")
ModelCmd.Flags().StringVarP(&modelCmdConfig.MigrationType, "migration-type", "", "fizz", "sets the type of migration files for model (sql or fizz)")
ModelCmd.Flags().BoolVarP(&modelCmdConfig.SkipMigration, "skip-migration", "s", false, "Skip creating a new fizz migration for this model.")
ModelCmd.Flags().StringVarP(&modelCmdConfig.ModelPath, "models-path", "", "models", "the path the model will be created in")
Expand Down

0 comments on commit aa19b35

Please sign in to comment.