Search code examples
gobuffalo

How can I use TOML fixtures to seed my database in a development environment using the Go Buffalo framework?


I am trying to seed my development database in the Go Buffalo framework using TOML fixtures. However, I am having trouble finding a clear example or documentation on how to do this.


Solution

  • To seed a database, you can use grifts. When creating a new application, there should be a dummy placeholder grift generated at grifts/db.go that looks like:

    package grifts
    
    import "github.com/gobuffalo/grift/grift"
    
    var _ = grift.Namespace("db", func() {
    
        grift.Desc("seed", "Seeds a database")
        grift.Add("seed", func(c *grift.Context) error {
            // Add DB seeding stuff here
            return nil
        })
    
    })
    

    I attempted to use model.LoadFixture("seed widgets") in a grift, but there is some panic because it is not in a test environment. I think DB seeding from toml fixtures is not supported directly but that would be a useful feature. However looking at the code from LoadFixture, we can construct our own fixture loading:

    Assuming you have a fixture with a scenario named name = "seed widgets":

    package grifts
    
    import (
        "fmt"
        "os"
        "strings"
    
        "github.com/gobuffalo/grift/grift"
        "github.com/gobuffalo/suite/v4"
        "github.com/gobuffalo/suite/v4/fix"
    )
    
    var _ = grift.Namespace("db", func() {
    
        grift.Desc("seed", "Seeds a database")
        grift.Add("seed", func(c *grift.Context) error {
            // The DB connection will connect to the environment set in `GO_ENV` (defaults to `test`)
            // Set this environment variable in your `.env` file to `development`
    
            // NOTE: it may be better to put seed fixtures in a different directory
            //       to seperate concerns
            model, err := suite.NewModelWithFixtures(os.DirFS("./fixtures"))
            if err != nil {
                return err
            }
    
            sc, err := fix.Find("seed widgets")
            if err != nil {
                return err
            }
    
            for _, table := range sc.Tables {
                for _, row := range table.Row {
                    q := "insert into " + table.Name
                    keys := []string{}
                    skeys := []string{}
                    for k := range row {
                        keys = append(keys, k)
                        skeys = append(skeys, ":"+k)
                    }
    
                    q = q + fmt.Sprintf(" (%s) values (%s)", strings.Join(keys, ","), strings.Join(skeys, ","))
                    if _, err = model.DB.Store.NamedExec(q, row); err != nil {
                        return err
                    }
                }
            }
    
            return nil
        })
    
    })