Skip to content

Commit

Permalink
Migrate fizz & SQL migrations generators to genny (#432)
Browse files Browse the repository at this point in the history
* Migrate fizz & SQL migrations generators to genny

* Add support for attributes to the fizz cmd

* Add support for attributes to the sql command
  • Loading branch information
stanislas-m authored Aug 30, 2019
1 parent 5959846 commit fa578ca
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 17 deletions.
31 changes: 31 additions & 0 deletions genny/fizz/cempty/create_empty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cempty

import (
"fmt"
"path/filepath"

"github.com/gobuffalo/genny"
)

// New creates a generator to make empty migration files.
func New(opts *Options) (*genny.Generator, error) {
g := genny.New()

if err := opts.Validate(); err != nil {
return g, err
}

var f genny.File
if opts.Type == "sql" {
f = genny.NewFileS(filepath.Join(opts.Path, fmt.Sprintf("%s.%s.up.sql", opts.Name, opts.Translator.Name())), "")
g.File(f)
f = genny.NewFileS(filepath.Join(opts.Path, fmt.Sprintf("%s.%s.down.sql", opts.Name, opts.Translator.Name())), "")
g.File(f)
} else {
f = genny.NewFileS(filepath.Join(opts.Path, opts.Name+".up.fizz"), "")
g.File(f)
f = genny.NewFileS(filepath.Join(opts.Path, opts.Name+".down.fizz"), "")
g.File(f)
}
return g, nil
}
36 changes: 36 additions & 0 deletions genny/fizz/cempty/create_empty_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cempty

import (
"testing"

"github.com/gobuffalo/genny/gentest"
"github.com/stretchr/testify/require"
)

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

g, err := New(&Options{
TableName: "widgets",
Name: "create_widgets",
})
r.NoError(err)

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

r.NoError(run.Run())

res := run.Results()

r.Len(res.Commands, 0)
r.Len(res.Files, 2)

f := res.Files[0]
r.Equal("migrations/create_widgets.down.fizz", f.Name())
r.Equal("", f.String())

f = res.Files[1]
r.Equal("migrations/create_widgets.up.fizz", f.Name())
r.Equal("", f.String())
}
7 changes: 7 additions & 0 deletions genny/fizz/cempty/mocks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package cempty

type mockTranslator struct{}

func (mockTranslator) Name() string {
return "test"
}
53 changes: 53 additions & 0 deletions genny/fizz/cempty/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cempty

import (
"fmt"
"time"

"github.com/gobuffalo/flect/name"
"github.com/pkg/errors"
)

var nowFunc = time.Now

type nameable interface {
Name() string
}

// Options for the empty migration generator.
type Options struct {
// TableName is the name of the table.
TableName string
// Name is the name of the generated file.
Name string
// Path is the dir path where to generate the migration files.
Path string
// Translator is a Fizz translator to use when asking for SQL migrations.
Translator nameable
// Type is the type of migration to generate (sql or fizz).
Type string
}

// Validate that options are usuable
func (opts *Options) Validate() error {
if len(opts.TableName) == 0 {
return errors.New("you must set a name for your table")
}
if len(opts.Path) == 0 {
opts.Path = "migrations"
}
if len(opts.Name) == 0 {
timestamp := nowFunc().UTC().Format("20060102150405")
opts.Name = fmt.Sprintf("%s_create_%s", timestamp, name.New(opts.TableName).Tableize())
}
if len(opts.Type) == 0 {
opts.Type = "fizz"
}
if opts.Type != "fizz" && opts.Type != "sql" {
return errors.Errorf("%s migration type is not allowed", opts.Type)
}
if opts.Type == "sql" && opts.Translator == nil {
return errors.New("sql migrations require a fizz translator")
}
return nil
}
52 changes: 52 additions & 0 deletions genny/fizz/cempty/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cempty

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

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

t0, _ := time.Parse(time.RFC3339, "2019-08-28T07:46:02Z")
nowFunc = func() time.Time { return t0 }
defer func() { nowFunc = time.Now }()

opts := &Options{}
err := opts.Validate()
r.Error(err)

opts.TableName = "widget"

err = opts.Validate()
r.NoError(err)

r.Equal(opts.Name, "20190828074602_create_widgets")
r.Equal("migrations", opts.Path)

// Custom migration name
opts.Name = "custom_migration"
err = opts.Validate()
r.NoError(err)

r.Equal(opts.Name, "custom_migration")
r.Equal("migrations", opts.Path)
}

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

opts := &Options{
TableName: "widget",
Type: "sql",
}
err := opts.Validate()
r.EqualError(err, "sql migrations require a fizz translator")

opts.Translator = mockTranslator{}
opts.Type = "aaa"
err = opts.Validate()
r.EqualError(err, "aaa migration type is not allowed")
}
4 changes: 3 additions & 1 deletion genny/fizz/ctable/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/pkg/errors"
)

var nowFunc = time.Now

// Options for the table create generator.
type Options struct {
// TableName is the name of the table.
Expand Down Expand Up @@ -39,7 +41,7 @@ func (opts *Options) Validate() error {
opts.Path = "migrations"
}
if len(opts.Name) == 0 {
timestamp := time.Now().UTC().Format("20060102150405")
timestamp := nowFunc().UTC().Format("20060102150405")
opts.Name = fmt.Sprintf("%s_create_%s", timestamp, name.New(opts.TableName).Tableize())
}
if len(opts.Type) == 0 {
Expand Down
15 changes: 14 additions & 1 deletion genny/fizz/ctable/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package ctable

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

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

t0, _ := time.Parse(time.RFC3339, "2019-08-28T07:46:02Z")
nowFunc = func() time.Time { return t0 }
defer func() { nowFunc = time.Now }()

opts := &Options{}
err := opts.Validate()
r.Error(err)
Expand All @@ -18,7 +23,15 @@ func Test_Options_Validate(t *testing.T) {
err = opts.Validate()
r.NoError(err)

r.Contains(opts.Name, "_create_widgets")
r.Equal(opts.Name, "20190828074602_create_widgets")
r.Equal("migrations", opts.Path)

// Custom migration name
opts.Name = "custom_migration"
err = opts.Validate()
r.NoError(err)

r.Equal(opts.Name, "custom_migration")
r.Equal("migrations", opts.Path)
}

Expand Down
65 changes: 57 additions & 8 deletions soda/cmd/generate/fizz_cmd.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package generate

import (
"errors"
"context"

"github.com/gobuffalo/pop"
"github.com/gobuffalo/pop/internal/defaults"
"github.com/gobuffalo/attrs"
"github.com/gobuffalo/genny"
"github.com/gobuffalo/logger"
"github.com/gobuffalo/pop/genny/fizz/cempty"
"github.com/gobuffalo/pop/genny/fizz/ctable"
"github.com/spf13/cobra"
)

Expand All @@ -14,11 +17,57 @@ var FizzCmd = &cobra.Command{
Aliases: []string{"migration"},
Short: "Generates Up/Down migrations for your database using fizz.",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("you must supply a name for your migration")
name := ""
if len(args) > 0 {
name = args[0]
}
cflag := cmd.Flag("path")
migrationPath := defaults.String(cflag.Value.String(), "./migrations")
return pop.MigrationCreate(migrationPath, args[0], "fizz", nil, nil)

var (
atts attrs.Attrs
err error
)
if len(args) > 1 {
atts, err = attrs.ParseArgs(args[1:]...)
if err != nil {
return err
}
}

run := genny.WetRunner(context.Background())

// Ensure the generator is as verbose as the old one.
lg := logger.New(logger.DebugLevel)
run.Logger = lg

p := cmd.Flag("path")
path := ""
if p != nil {
path = p.Value.String()
}

if len(atts) == 0 {
g, err := cempty.New(&cempty.Options{
TableName: name,
Path: path,
Type: "fizz",
})
if err != nil {
return err
}
run.With(g)
} else {
g, err := ctable.New(&ctable.Options{
TableName: name,
Path: path,
Type: "fizz",
Attrs: atts,
})
if err != nil {
return err
}
run.With(g)
}

return run.Run()
},
}
32 changes: 32 additions & 0 deletions soda/cmd/generate/fizz_cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package generate

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/gobuffalo/envy"
"github.com/stretchr/testify/require"
)

func Test_FizzCmd_NoArg(t *testing.T) {
r := require.New(t)
c := FizzCmd
c.SetArgs([]string{})

gp, err := envy.MustGet("GOPATH")
r.NoError(err)
cpath := filepath.Join(gp, "src", "github.com", "gobuffalo")
tdir, err := ioutil.TempDir(cpath, "testapp")
r.NoError(err)
defer os.RemoveAll(tdir)

pwd, err := os.Getwd()
r.NoError(err)
os.Chdir(tdir)
defer os.Chdir(pwd)

err = c.Execute()
r.EqualError(err, "you must set a name for your table")
}
Loading

0 comments on commit fa578ca

Please sign in to comment.