Database Seeding
Table of Contents
With our app in a healthy place, we can add database seeding. This is going to be quick because all we’re going to have
to do is write a handful of ent
create methods. We can make this more advanced with environment specific config and/or
external files that we can embed using embed.FS
.
Since we don’t need anything too complicated just yet, let’s keep our seeding command simple. We can always expand on it later if we need additional functionality.
Let’s start with creating a skeleton for the Cobra command for our migrate
command. It’s pretty standard boilerplate
code from what we’ve seen before on Cobra:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var seedCmd = &cobra.Command{
Use: "seed",
Short: "Seed the database with initial values",
RunE: runSeed,
}
func init() {
rootCmd.AddCommand(seedCmd)
}
func runSeed(cmd *cobra.Command, args []string) error {
return fmt.Errorf("not implemented")
}
Here we’re just creating a new seedCmd
with the command name (Use
) of seed
and a short description (the Short
field) and using our runE
wrapper for the run command. Also, don’t forget to add this command to the rootCmd
otherwise this command won’t ba available to us when we try to run the app.
With the boilerplate for it in place we can implement our runSeed func to seed our database:
func runSeed(cmd *cobra.Command, args []string) (err error) {
cfg := config.GetApp()
entClient, err := ent.Open(cfg.Database.Driver, cfg.Database.URL)
if err != nil {
return
}
defer entClient.Close()
notes := []*ent.NoteCreate{
entClient.Note.Create().
SetTitle("My First Note").
SetBody("## My First Note Section\n\nSome content for the note. With a [link](https://blog.miu.guru) to a cool site!"),
entClient.Note.Create().
SetTitle("My Second Note").
SetBody("## My Other Note\n\nMore random note content...\n\n- with\n- a\n- list\n\nAll this formatting and no where to go."),
}
fmt.Println("Seeding notes...")
err = entClient.Note.CreateBulk(notes...).Exec(cmd.Context())
// create additional seeds here
return
}
Here we are bulk creating notes with some basic Markdown to test our app with. Notice that we have NoteCreate
structs
being generated by using the ent
client’s Create()
method for the model but we don’t commit with
Save(context.Context)
or Exec(context.Context)
when we’re done. Then when we are ready we can pass all of our
builders into the CreateBulk()
method of the ent
client.
With this all in place, we can run our seed command:
go run . seed
You should just see the output:
outputSeeding notes...
We can also check out our new command in the Cobra help:
go run . -h
You should see the seed
command and its description of what it does:
GentQL backend application services. Usage: gentql [command] Available Commands: api Start the API services for gentql completion Generate the autocompletion script for the specified shell help Help about any command migrate Migrate the database between versions seed Seed the database with initial values Flags: -h, --help help for gentql Use "gentql [command] --help" for more information about a command.
We can combine this with more advanced create options to ensure we don’t duplicate some records when they shouldn’t be added multiple times in a row. Typically, when I set up seeding I’ll use a testing user or some other unique data that can be checked against to ensure there isn’t duplicate data, in the case that’s not desirable.