Add struct tags flag
This commit is contained in:
parent
e35ecd76c1
commit
4e8191b8dd
7 changed files with 116 additions and 10 deletions
|
@ -7,6 +7,7 @@ type Config struct {
|
||||||
OutFolder string
|
OutFolder string
|
||||||
BaseDir string
|
BaseDir string
|
||||||
ExcludeTables []string
|
ExcludeTables []string
|
||||||
|
Tags []string
|
||||||
Debug bool
|
Debug bool
|
||||||
NoTests bool
|
NoTests bool
|
||||||
NoHooks bool
|
NoHooks bool
|
||||||
|
|
11
main.go
11
main.go
|
@ -64,6 +64,7 @@ func main() {
|
||||||
rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
|
rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")
|
||||||
rootCmd.PersistentFlags().StringP("basedir", "b", "", "The base directory has the templates and templates_test folders")
|
rootCmd.PersistentFlags().StringP("basedir", "b", "", "The base directory has the templates and templates_test folders")
|
||||||
rootCmd.PersistentFlags().StringSliceP("exclude", "x", nil, "Tables to be excluded from the generated package")
|
rootCmd.PersistentFlags().StringSliceP("exclude", "x", nil, "Tables to be excluded from the generated package")
|
||||||
|
rootCmd.PersistentFlags().StringSliceP("tag", "t", nil, "Struct tags to be included on your models in addition to json, yaml, toml")
|
||||||
rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
|
rootCmd.PersistentFlags().BoolP("debug", "d", false, "Debug mode prints stack traces on error")
|
||||||
rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
|
rootCmd.PersistentFlags().BoolP("no-tests", "", false, "Disable generated go test files")
|
||||||
rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
|
rootCmd.PersistentFlags().BoolP("no-hooks", "", false, "Disable hooks feature for your models")
|
||||||
|
@ -114,7 +115,7 @@ func preRun(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG: https://github.com/spf13/viper/issues/200
|
// BUG: https://github.com/spf13/viper/issues/200
|
||||||
// Look up the value of ExcludeTables directly from PFlags in Cobra if we
|
// Look up the value of ExcludeTables & Tags directly from PFlags in Cobra if we
|
||||||
// detect a malformed value coming out of viper.
|
// detect a malformed value coming out of viper.
|
||||||
// Once the bug is fixed we'll be able to move this into the init above
|
// Once the bug is fixed we'll be able to move this into the init above
|
||||||
cmdConfig.ExcludeTables = viper.GetStringSlice("exclude")
|
cmdConfig.ExcludeTables = viper.GetStringSlice("exclude")
|
||||||
|
@ -125,6 +126,14 @@ func preRun(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmdConfig.Tags = viper.GetStringSlice("tag")
|
||||||
|
if len(cmdConfig.Tags) == 1 && strings.HasPrefix(cmdConfig.Tags[0], "[") {
|
||||||
|
cmdConfig.Tags, err = cmd.PersistentFlags().GetStringSlice("tag")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if viper.IsSet("postgres.dbname") {
|
if viper.IsSet("postgres.dbname") {
|
||||||
cmdConfig.Postgres = PostgresConfig{
|
cmdConfig.Postgres = PostgresConfig{
|
||||||
User: viper.GetString("postgres.user"),
|
User: viper.GetString("postgres.user"),
|
||||||
|
|
23
sqlboiler.go
23
sqlboiler.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
@ -82,6 +83,11 @@ func New(config *Config) (*State, error) {
|
||||||
return nil, errors.Wrap(err, "unable to initialize templates")
|
return nil, errors.Wrap(err, "unable to initialize templates")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = s.initTags(config.Tags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "unable to initialize struct tags")
|
||||||
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,6 +132,7 @@ func (s *State) Run(includeTests bool) error {
|
||||||
PkgName: s.Config.PkgName,
|
PkgName: s.Config.PkgName,
|
||||||
NoHooks: s.Config.NoHooks,
|
NoHooks: s.Config.NoHooks,
|
||||||
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
NoAutoTimestamps: s.Config.NoAutoTimestamps,
|
||||||
|
Tags: s.Config.Tags,
|
||||||
|
|
||||||
StringFuncs: templateStringMappers,
|
StringFuncs: templateStringMappers,
|
||||||
}
|
}
|
||||||
|
@ -250,6 +257,22 @@ func (s *State) initTables(exclude []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tags must be in a format like: json, xml, etc.
|
||||||
|
var rgxValidTag = regexp.MustCompile(`[a-zA-Z_\.]+`)
|
||||||
|
|
||||||
|
// initTags removes duplicate tags and validates the format
|
||||||
|
// of all user tags are simple strings without quotes: [a-zA-Z_\.]+
|
||||||
|
func (s *State) initTags(tags []string) error {
|
||||||
|
s.Config.Tags = removeDuplicates(s.Config.Tags)
|
||||||
|
for _, v := range s.Config.Tags {
|
||||||
|
if !rgxValidTag.MatchString(v) {
|
||||||
|
return errors.New("Invalid tag format %q supplied, only specify name, eg: xml")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// initOutFolder creates the folder that will hold the generated output.
|
// initOutFolder creates the folder that will hold the generated output.
|
||||||
func (s *State) initOutFolder() error {
|
func (s *State) initOutFolder() error {
|
||||||
return os.MkdirAll(s.Config.OutFolder, os.ModePerm)
|
return os.MkdirAll(s.Config.OutFolder, os.ModePerm)
|
||||||
|
|
|
@ -487,3 +487,35 @@ func ContainsAny(a []string, finds ...string) bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateTags converts a slice of tag strings into tags that
|
||||||
|
// can be passed onto the end of a struct, for example:
|
||||||
|
// tags: ["xml", "db"] convert to: xml:"column_name" db:"column_name"
|
||||||
|
func GenerateTags(tags []string, columnName string) string {
|
||||||
|
buf := GetBuffer()
|
||||||
|
defer PutBuffer(buf)
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
buf.WriteString(tag)
|
||||||
|
buf.WriteString(`:"`)
|
||||||
|
buf.WriteString(columnName)
|
||||||
|
buf.WriteString(`" `)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateIgnoreTags converts a slice of tag strings into
|
||||||
|
// ignore tags that can be passed onto the end of a struct, for example:
|
||||||
|
// tags: ["xml", "db"] convert to: xml:"-" db:"-"
|
||||||
|
func GenerateIgnoreTags(tags []string) string {
|
||||||
|
buf := GetBuffer()
|
||||||
|
defer PutBuffer(buf)
|
||||||
|
|
||||||
|
for _, tag := range tags {
|
||||||
|
buf.WriteString(tag)
|
||||||
|
buf.WriteString(`:"-" `)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
|
@ -426,3 +426,41 @@ func TestContainsAny(t *testing.T) {
|
||||||
t.Errorf("Should not return true")
|
t.Errorf("Should not return true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenerateTags(t *testing.T) {
|
||||||
|
tags := GenerateTags([]string{}, "col_name")
|
||||||
|
if tags != "" {
|
||||||
|
t.Errorf("Expected empty string, got %s", tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = GenerateTags([]string{"xml"}, "col_name")
|
||||||
|
exp := `xml:"col_name" `
|
||||||
|
if tags != exp {
|
||||||
|
t.Errorf("expected %s, got %s", exp, tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = GenerateTags([]string{"xml", "db"}, "col_name")
|
||||||
|
exp = `xml:"col_name" db:"col_name" `
|
||||||
|
if tags != exp {
|
||||||
|
t.Errorf("expected %s, got %s", exp, tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGenerateIgnoreTags(t *testing.T) {
|
||||||
|
tags := GenerateIgnoreTags([]string{})
|
||||||
|
if tags != "" {
|
||||||
|
t.Errorf("Expected empty string, got %s", tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = GenerateIgnoreTags([]string{"xml"})
|
||||||
|
exp := `xml:"-" `
|
||||||
|
if tags != exp {
|
||||||
|
t.Errorf("expected %s, got %s", exp, tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = GenerateIgnoreTags([]string{"xml", "db"})
|
||||||
|
exp = `xml:"-" db:"-" `
|
||||||
|
if tags != exp {
|
||||||
|
t.Errorf("expected %s, got %s", exp, tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
templates.go
13
templates.go
|
@ -20,6 +20,7 @@ type templateData struct {
|
||||||
PkgName string
|
PkgName string
|
||||||
NoHooks bool
|
NoHooks bool
|
||||||
NoAutoTimestamps bool
|
NoAutoTimestamps bool
|
||||||
|
Tags []string
|
||||||
|
|
||||||
StringFuncs map[string]func(string) string
|
StringFuncs map[string]func(string) string
|
||||||
}
|
}
|
||||||
|
@ -124,11 +125,13 @@ var templateFunctions = template.FuncMap{
|
||||||
"camelCase": strmangle.CamelCase,
|
"camelCase": strmangle.CamelCase,
|
||||||
|
|
||||||
// String Slice ops
|
// String Slice ops
|
||||||
"join": func(sep string, slice []string) string { return strings.Join(slice, sep) },
|
"join": func(sep string, slice []string) string { return strings.Join(slice, sep) },
|
||||||
"joinSlices": strmangle.JoinSlices,
|
"joinSlices": strmangle.JoinSlices,
|
||||||
"stringMap": strmangle.StringMap,
|
"stringMap": strmangle.StringMap,
|
||||||
"prefixStringSlice": strmangle.PrefixStringSlice,
|
"prefixStringSlice": strmangle.PrefixStringSlice,
|
||||||
"containsAny": strmangle.ContainsAny,
|
"containsAny": strmangle.ContainsAny,
|
||||||
|
"generateTags": strmangle.GenerateTags,
|
||||||
|
"generateIgnoreTags": strmangle.GenerateIgnoreTags,
|
||||||
|
|
||||||
// String Map ops
|
// String Map ops
|
||||||
"makeStringMap": strmangle.MakeStringMap,
|
"makeStringMap": strmangle.MakeStringMap,
|
||||||
|
|
|
@ -2,22 +2,22 @@
|
||||||
{{.Function.Name}} *{{.ForeignTable.NameGo}}
|
{{.Function.Name}} *{{.ForeignTable.NameGo}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- $dot := . -}}
|
||||||
{{- $tableNameSingular := .Table.Name | singular -}}
|
{{- $tableNameSingular := .Table.Name | singular -}}
|
||||||
{{- $modelName := $tableNameSingular | titleCase -}}
|
{{- $modelName := $tableNameSingular | titleCase -}}
|
||||||
{{- $modelNameCamel := $tableNameSingular | camelCase -}}
|
{{- $modelNameCamel := $tableNameSingular | camelCase -}}
|
||||||
// {{$modelName}} is an object representing the database table.
|
// {{$modelName}} is an object representing the database table.
|
||||||
type {{$modelName}} struct {
|
type {{$modelName}} struct {
|
||||||
{{range $column := .Table.Columns -}}
|
{{range $column := .Table.Columns -}}
|
||||||
{{titleCase $column.Name}} {{$column.Type}} `boil:"{{$column.Name}}" json:"{{$column.Name}}{{if $column.Nullable}},omitempty{{end}}" toml:"{{$column.Name}}" yaml:"{{$column.Name}}{{if $column.Nullable}},omitempty{{end}}"`
|
{{titleCase $column.Name}} {{$column.Type}} `{{generateTags $dot.Tags $column.Name}}boil:"{{$column.Name}}" json:"{{$column.Name}}{{if $column.Nullable}},omitempty{{end}}" toml:"{{$column.Name}}" yaml:"{{$column.Name}}{{if $column.Nullable}},omitempty{{end}}"`
|
||||||
{{end -}}
|
{{end -}}
|
||||||
{{- if .Table.IsJoinTable -}}
|
{{- if .Table.IsJoinTable -}}
|
||||||
{{- else}}
|
{{- else}}
|
||||||
R *{{$modelNameCamel}}R `boil:"-" json:"-" toml:"-" yaml:"-"`
|
R *{{$modelNameCamel}}R `{{generateIgnoreTags $dot.Tags}}boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||||
L {{$modelNameCamel}}L `boil:"-" json:"-" toml:"-" yaml:"-"`
|
L {{$modelNameCamel}}L `{{generateIgnoreTags $dot.Tags}}boil:"-" json:"-" toml:"-" yaml:"-"`
|
||||||
{{end -}}
|
{{end -}}
|
||||||
}
|
}
|
||||||
|
|
||||||
{{- $dot := . -}}
|
|
||||||
{{- if .Table.IsJoinTable -}}
|
{{- if .Table.IsJoinTable -}}
|
||||||
{{- else}}
|
{{- else}}
|
||||||
// {{$modelNameCamel}}R is where relationships are stored.
|
// {{$modelNameCamel}}R is where relationships are stored.
|
||||||
|
|
Loading…
Add table
Reference in a new issue