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

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

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,看起来像这样:

  1. package grifts
  2. import "github.com/gobuffalo/grift/grift"
  3. var _ = grift.Namespace("db", func() {
  4. grift.Desc("seed", "Seeds a database")
  5. grift.Add("seed", func(c *grift.Context) error {
  6. // 在这里添加数据库种子内容
  7. return nil
  8. })
  9. })

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

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

  1. package grifts
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "github.com/gobuffalo/grift/grift"
  7. "github.com/gobuffalo/suite/v4"
  8. "github.com/gobuffalo/suite/v4/fix"
  9. )
  10. var _ = grift.Namespace("db", func() {
  11. grift.Desc("seed", "Seeds a database")
  12. grift.Add("seed", func(c *grift.Context) error {
  13. // DB连接将连接到在`GO_ENV`中设置的环境(默认为`test`)
  14. // 在您的`.env`文件中将此环境变量设置为`development`
  15. // 注意:最好将种子fixtures放在不同的目录中
  16. // 以分离关注点
  17. model, err := suite.NewModelWithFixtures(os.DirFS("./fixtures"))
  18. if err != nil {
  19. return err
  20. }
  21. sc, err := fix.Find("seed widgets")
  22. if err != nil {
  23. return err
  24. }
  25. for _, table := range sc.Tables {
  26. for _, row := range table.Row {
  27. q := "insert into " + table.Name
  28. keys := []string{}
  29. skeys := []string{}
  30. for k := range row {
  31. keys = append(keys, k)
  32. skeys = append(skeys, ":"+k)
  33. }
  34. q = q + fmt.Sprintf(" (%s) values (%s)", strings.Join(keys, ","), strings.Join(skeys, ","))
  35. if _, err = model.DB.Store.NamedExec(q, row); err != nil {
  36. return err
  37. }
  38. }
  39. }
  40. return nil
  41. })
  42. })
英文:

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:

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

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":

  1. package grifts
  2. import (
  3. "fmt"
  4. "os"
  5. "strings"
  6. "github.com/gobuffalo/grift/grift"
  7. "github.com/gobuffalo/suite/v4"
  8. "github.com/gobuffalo/suite/v4/fix"
  9. )
  10. var _ = grift.Namespace("db", func() {
  11. grift.Desc("seed", "Seeds a database")
  12. grift.Add("seed", func(c *grift.Context) error {
  13. // The DB connection will connect to the environment set in `GO_ENV` (defaults to `test`)
  14. // Set this environment variable in your `.env` file to `development`
  15. // NOTE: it may be better to put seed fixtures in a different directory
  16. // to seperate concerns
  17. model, err := suite.NewModelWithFixtures(os.DirFS("./fixtures"))
  18. if err != nil {
  19. return err
  20. }
  21. sc, err := fix.Find("seed widgets")
  22. if err != nil {
  23. return err
  24. }
  25. for _, table := range sc.Tables {
  26. for _, row := range table.Row {
  27. q := "insert into " + table.Name
  28. keys := []string{}
  29. skeys := []string{}
  30. for k := range row {
  31. keys = append(keys, k)
  32. skeys = append(skeys, ":"+k)
  33. }
  34. q = q + fmt.Sprintf(" (%s) values (%s)", strings.Join(keys, ","), strings.Join(skeys, ","))
  35. if _, err = model.DB.Store.NamedExec(q, row); err != nil {
  36. return err
  37. }
  38. }
  39. }
  40. return nil
  41. })
  42. })

答案2

得分: 1

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

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

actions/actions_test.go

  1. package actions
  2. import (
  3. "os"
  4. "testing"
  5. "github.com/gobuffalo/suite/v4"
  6. )
  7. type ActionSuite struct {
  8. *suite.Action
  9. }
  10. func Test_ActionSuite(t *testing.T) {
  11. action, err := suite.NewActionWithFixtures(App(), os.DirFS("../fixtures"))
  12. if err != nil {
  13. t.Fatal(err)
  14. }
  15. as := &ActionSuite{
  16. Action: action,
  17. }
  18. suite.Run(t, as)
  19. }

models/models_test.go

  1. package models
  2. import (
  3. "os"
  4. "testing"
  5. "github.com/gobuffalo/suite/v4"
  6. )
  7. type ModelSuite struct {
  8. *suite.Model
  9. }
  10. func Test_ModelSuite(t *testing.T) {
  11. model, err := suite.NewModelWithFixtures(os.DirFS("../fixtures"))
  12. if err != nil {
  13. t.Fatal(err)
  14. }
  15. as := &ModelSuite{
  16. Model: model,
  17. }
  18. suite.Run(t, as)
  19. }

fixtures/widgets.toml

  1. [[scenario]]
  2. name = "lots of widgets"
  3. [[scenario.table]]
  4. name = "widgets"
  5. [[scenario.table.row]]
  6. id = "<%= uuidNamed("widget") %>"
  7. name = "This is widget #1"
  8. body = "some widget body"
  9. created_at = "<%= now() %>"
  10. updated_at = "<%= now() %>"
  11. [[scenario.table.row]]
  12. id = "<%= uuid() %>"
  13. name = "This is widget #2"
  14. body = "some widget body"
  15. created_at = "<%= now() %>"
  16. updated_at = "<%= now() %>"
  17. [[scenario.table]]
  18. name = "users"
  19. [[scenario.table.row]]
  20. id = "<%= uuid() %>"
  21. name = "Mark Bates"
  22. admin = true
  23. price = 19.99
  24. widget_id = "<%= uuidNamed("widget") %>"
  25. created_at = "<%= now() %>"
  26. updated_at = "<%= now() %>"

actions/widgets_test.go

  1. func (as *ActionSuite) Test_WidgetsResource_List() {
  2. as.LoadFixture("lots of widgets")
  3. res := as.HTML("/widgets").Get()
  4. body := res.Body.String()
  5. as.Contains(body, "widget #1")
  6. as.Contains(body, "widget #2")
  7. }

models/widget_test.go

  1. func (ms *ModelSuite) Test_Widget_SomeModelMethod() {
  2. ms.LoadFixture("lots of widgets")
  3. var widgets []Widget
  4. if err := DB.All(&widgets); err != nil {
  5. ms.Fail(err.Error())
  6. }
  7. for _, widget := range widgets {
  8. ms.Equal("some value", widget.SomeModelMethod())
  9. }
  10. }

database.yml

  1. test:
  2. 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

  1. package actions
  2. import (
  3. &quot;os&quot;
  4. &quot;testing&quot;
  5. &quot;github.com/gobuffalo/suite/v4&quot;
  6. )
  7. type ActionSuite struct {
  8. *suite.Action
  9. }
  10. func Test_ActionSuite(t *testing.T) {
  11. action, err := suite.NewActionWithFixtures(App(), os.DirFS(&quot;../fixtures&quot;))
  12. if err != nil {
  13. t.Fatal(err)
  14. }
  15. as := &amp;ActionSuite{
  16. Action: action,
  17. }
  18. suite.Run(t, as)
  19. }

models/models_test.go

  1. package models
  2. import (
  3. &quot;os&quot;
  4. &quot;testing&quot;
  5. &quot;github.com/gobuffalo/suite/v4&quot;
  6. )
  7. type ModelSuite struct {
  8. *suite.Model
  9. }
  10. func Test_ModelSuite(t *testing.T) {
  11. model, err := suite.NewModelWithFixtures(os.DirFS(&quot;../fixtures&quot;))
  12. if err != nil {
  13. t.Fatal(err)
  14. }
  15. as := &amp;ModelSuite{
  16. Model: model,
  17. }
  18. suite.Run(t, as)
  19. }

fixtures/widgets.toml

  1. [[scenario]]
  2. name = &quot;lots of widgets&quot;
  3. [[scenario.table]]
  4. name = &quot;widgets&quot;
  5. [[scenario.table.row]]
  6. id = &quot;&lt;%= uuidNamed(&quot;widget&quot;) %&gt;&quot;
  7. name = &quot;This is widget #1&quot;
  8. body = &quot;some widget body&quot;
  9. created_at = &quot;&lt;%= now() %&gt;&quot;
  10. updated_at = &quot;&lt;%= now() %&gt;&quot;
  11. [[scenario.table.row]]
  12. id = &quot;&lt;%= uuid() %&gt;&quot;
  13. name = &quot;This is widget #2&quot;
  14. body = &quot;some widget body&quot;
  15. created_at = &quot;&lt;%= now() %&gt;&quot;
  16. updated_at = &quot;&lt;%= now() %&gt;&quot;
  17. [[scenario.table]]
  18. name = &quot;users&quot;
  19. [[scenario.table.row]]
  20. id = &quot;&lt;%= uuid() %&gt;&quot;
  21. name = &quot;Mark Bates&quot;
  22. admin = true
  23. price = 19.99
  24. widget_id = &quot;&lt;%= uuidNamed(&quot;widget&quot;) %&gt;&quot;
  25. created_at = &quot;&lt;%= now() %&gt;&quot;
  26. updated_at = &quot;&lt;%= now() %&gt;&quot;

actions/widgets_test.go

  1. func (as *ActionSuite) Test_WidgetsResource_List() {
  2. as.LoadFixture(&quot;lots of widgets&quot;)
  3. res := as.HTML(&quot;/widgets&quot;).Get()
  4. body := res.Body.String()
  5. as.Contains(body, &quot;widget #1&quot;)
  6. as.Contains(body, &quot;widget #2&quot;)
  7. }

models/widget_test.go

  1. func (ms *ModelSuite) Test_Widget_SomeModelMethod() {
  2. ms.LoadFixture(&quot;lots of widgets&quot;)
  3. var widgets []Widget
  4. if err := DB.All(&amp;widgets); err != nil {
  5. ms.Fail(err.Error())
  6. }
  7. for _, widget := range widgets {
  8. ms.Equal(&quot;some value&quot;, widget.SomeModelMethod())
  9. }
  10. }

database.yml

  1. test:
  2. 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:

确定