如何在使用Go Buffalo框架的开发环境中,使用TOML fixtures来填充数据库?

huangapple go评论98阅读模式
英文:

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

问题

我正在尝试使用 TOML fixtures 在 Go Buffalo 框架中填充我的开发数据库。然而,我在如何做到这一点方面遇到了困难,找不到清晰的示例或文档。

英文:

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.

答案1

得分: 4

要种子数据库,您可以使用grifts。在创建新应用程序时,应该在grifts/db.go中生成一个虚拟的占位符grift,看起来像这样:

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 {
		// 在这里添加数据库种子内容
		return nil
	})

})

我尝试在grift中使用model.LoadFixture("seed widgets"),但由于不在测试环境中,所以出现了一些恐慌。我认为直接从toml fixtures中支持数据库种子不是直接支持的,但这将是一个有用的功能。然而,通过查看LoadFixture的代码,我们可以构建自己的fixture加载:

假设您有一个名为name = "seed widgets"的fixture场景:

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 {
		// DB连接将连接到在`GO_ENV`中设置的环境(默认为`test`)
		// 在您的`.env`文件中将此环境变量设置为`development`

		// 注意:最好将种子fixtures放在不同的目录中
		// 以分离关注点
		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
	})

})
英文:

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
	})

})

答案2

得分: 1

你可以在这里找到关于测试和夹具的所有所需信息:https://github.com/gobuffalo/suite

这是一个关于操作和模型测试的基本示例:

actions/actions_test.go

package actions

import (
    "os"
    "testing"

    "github.com/gobuffalo/suite/v4"
)

type ActionSuite struct {
    *suite.Action
}

func Test_ActionSuite(t *testing.T) {
    action, err := suite.NewActionWithFixtures(App(), os.DirFS("../fixtures"))
    if err != nil {
        t.Fatal(err)
    }

    as := &ActionSuite{
        Action: action,
    }
    suite.Run(t, as)
}

models/models_test.go

package models

import (
    "os"
    "testing"

    "github.com/gobuffalo/suite/v4"
)

type ModelSuite struct {
    *suite.Model
}

func Test_ModelSuite(t *testing.T) {
    model, err := suite.NewModelWithFixtures(os.DirFS("../fixtures"))
    if err != nil {
        t.Fatal(err)
    }

    as := &ModelSuite{
        Model:  model,
    }
    suite.Run(t, as)
}

fixtures/widgets.toml

[[scenario]]
name = "lots of widgets"

  [[scenario.table]]
    name = "widgets"

    [[scenario.table.row]]
      id = "<%= uuidNamed("widget") %>"
      name = "This is widget #1"
      body = "some widget body"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

    [[scenario.table.row]]
      id = "<%= uuid() %>"
      name = "This is widget #2"
      body = "some widget body"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

  [[scenario.table]]
    name = "users"

    [[scenario.table.row]]
      id = "<%= uuid() %>"
      name = "Mark Bates"
      admin = true
      price = 19.99
      widget_id = "<%= uuidNamed("widget") %>"
      created_at = "<%= now() %>"
      updated_at = "<%= now() %>"

actions/widgets_test.go

func (as *ActionSuite) Test_WidgetsResource_List() {
    as.LoadFixture("lots of widgets")
    res := as.HTML("/widgets").Get()

    body := res.Body.String()
    as.Contains(body, "widget #1")
    as.Contains(body, "widget #2")
}

models/widget_test.go

func (ms *ModelSuite) Test_Widget_SomeModelMethod() {
    ms.LoadFixture("lots of widgets")

    var widgets []Widget
    if err := DB.All(&widgets); err != nil {
        ms.Fail(err.Error())
    }

    for _, widget := range widgets {
        ms.Equal("some value", widget.SomeModelMethod())
    }
}

database.yml

test:
  url: {{envOr "TEST_DATABASE_URL" "postgres://postgres@127.0.0.1:5432/medicare_65_quote_test?sslmode=disable"}}
英文:

You can find all the information you need about testing and fixtures here: https://github.com/gobuffalo/suite

Here is a basic example of actions and model tests:

actions/actions_test.go

package actions

import (
    &quot;os&quot;
    &quot;testing&quot;

    &quot;github.com/gobuffalo/suite/v4&quot;
)

type ActionSuite struct {
    *suite.Action
}

func Test_ActionSuite(t *testing.T) {
    action, err := suite.NewActionWithFixtures(App(), os.DirFS(&quot;../fixtures&quot;))
    if err != nil {
        t.Fatal(err)
    }

    as := &amp;ActionSuite{
        Action: action,
    }
    suite.Run(t, as)
}

models/models_test.go

package models

import (
    &quot;os&quot;
    &quot;testing&quot;

    &quot;github.com/gobuffalo/suite/v4&quot;
)

type ModelSuite struct {
    *suite.Model
}

func Test_ModelSuite(t *testing.T) {
    model, err := suite.NewModelWithFixtures(os.DirFS(&quot;../fixtures&quot;))
    if err != nil {
        t.Fatal(err)
    }

	as := &amp;ModelSuite{
		Model:  model,
    }
    suite.Run(t, as)
}

fixtures/widgets.toml

[[scenario]]
name = &quot;lots of widgets&quot;

  [[scenario.table]]
    name = &quot;widgets&quot;

    [[scenario.table.row]]
      id = &quot;&lt;%= uuidNamed(&quot;widget&quot;) %&gt;&quot;
      name = &quot;This is widget #1&quot;
      body = &quot;some widget body&quot;
      created_at = &quot;&lt;%= now() %&gt;&quot;
      updated_at = &quot;&lt;%= now() %&gt;&quot;

    [[scenario.table.row]]
      id = &quot;&lt;%= uuid() %&gt;&quot;
      name = &quot;This is widget #2&quot;
      body = &quot;some widget body&quot;
      created_at = &quot;&lt;%= now() %&gt;&quot;
      updated_at = &quot;&lt;%= now() %&gt;&quot;

  [[scenario.table]]
    name = &quot;users&quot;

    [[scenario.table.row]]
      id = &quot;&lt;%= uuid() %&gt;&quot;
      name = &quot;Mark Bates&quot;
      admin = true
      price = 19.99
      widget_id = &quot;&lt;%= uuidNamed(&quot;widget&quot;) %&gt;&quot;
      created_at = &quot;&lt;%= now() %&gt;&quot;
      updated_at = &quot;&lt;%= now() %&gt;&quot;

actions/widgets_test.go

func (as *ActionSuite) Test_WidgetsResource_List() {
    as.LoadFixture(&quot;lots of widgets&quot;)
    res := as.HTML(&quot;/widgets&quot;).Get()

    body := res.Body.String()
    as.Contains(body, &quot;widget #1&quot;)
    as.Contains(body, &quot;widget #2&quot;)
}

models/widget_test.go

func (ms *ModelSuite) Test_Widget_SomeModelMethod() {
	ms.LoadFixture(&quot;lots of widgets&quot;)

	var widgets []Widget
	if err := DB.All(&amp;widgets); err != nil {
		ms.Fail(err.Error())
	}

	for _, widget := range widgets {
		ms.Equal(&quot;some value&quot;, widget.SomeModelMethod())
	}
}

database.yml

test:
  url: {{envOr &quot;TEST_DATABASE_URL&quot; &quot;postgres://postgres@127.0.0.1:5432/medicare_65_quote_test?sslmode=disable&quot;}}

huangapple
  • 本文由 发表于 2023年1月19日 00:56:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75162669.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定