soda pop

Thinking I might want to write another Go webapp with some database in the background I wanted to play around with DBs first.

I decided to use pop for this.

Let’s create the project:

mkdir -p  ~/.go/src/github.com/jubalh/soda-pop-example
cd ~/.go/src/github.com/jubalh/soda-pop-example

And define a SQLite test database:

$ vi database.yml

development:
  dialect: "sqlite3"
  database: "./db.sqlite"

Our example program looks like this for now:

package main

import (
  "fmt"
  "log"

  "github.com/gobuffalo/pop"
)

func main() {
  fmt.Println("This is a Go database test program")
}

It’s time to install pop and it’s cli frontend soda:

go get github.com/gobuffalo/pop/...
go install github.com/gobuffalo/pop/soda

Tell soda do create the database:

$ soda create development
v4.0.2

created database ./db.sqlite

Now we can add the code to our Go file to connect to the database:

db, err := pop.Connect("development")
if err != nil {
  log.Panic(err)
}

Model

A model is something we fill with values and put into our database. In the code we can use it as a struct and pop takes care of its representation in the DB via the model we specified.

soda generate model user firstname:text lastname:text
v4.0.2

	create  models/user.go
	create  models/user_test.go
		run  goimports -w main.go models/user.go models/user_test.go
> migrations/20180228135043_create_users.up.fizz
> migrations/20180228135043_create_users.down.fizz

Look at the generated files to learn about them.

Apply to database:

soda migrate up
v4.0.2

> create_users

0.0741 seconds
dumped schema for ./db.sqlite

We can add users inside our program like this:

user := models.User{Firstname: "Vincent", Lastname: "Vega"}
_, err = db.ValidateAndSave(&user)                                                                                                                                                           
  if err != nil {
    log.Panic(err)
  }
fmt.Printf("Added %s to database\n", user.Firstname)

user = models.User{Firstname: "Jules", Lastname: "Winnfield"}
_, err = db.ValidateAndSave(&user)
if err != nil {
  log.Panic(err)
}
fmt.Printf("Added %s to database\n", user.Firstname)

Running it we get:

$ go run main.go
This is a Go database test program
Added Vincent to database
Added Jules to database

Through looking at the models/user.go file we understood what the struct looked like that soda created for us. Now let’s take a look at the SQLite table:

sqlite3 ./db.sqlite 
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> SELECT * FROM users;
fd38017c-5426-42bb-90b3-40a76ee3316f|Vincent|Vega|2018-02-28 14:59:22.864084017+01:00|2018-02-28 14:59:22.864084669+01:00
a57aa8a3-ba52-453c-a337-1453570c72a6|Jules|Winnfield|2018-02-28 14:59:22.897798215+01:00|2018-02-28 14:59:22.897801007+01:00
sqlite> .exit

Modifying a model

Only thing we forgot is that those folks have an age too. (No, no birthdate, they don’t age)

$ soda generate fizz add_age
v4.0.2

> migrations/20180228141319_add_age.up.fizz
> migrations/20180228141319_add_age.down.fizz

$ vi migrations/20180228141319_add_age.up.fizz
add_column("users", "age", "integer", {"default": "23"}) 

$ vi migrations/20180228141319_add_age.down.fizz
drop_column("users", "age")

Also append the line Age int json:“age” db:“age”`` to the User struct in models/user.go. Now we update or migrate the database to the new scheme:

$ soda migrate
v4.0.2

> add_age

0.0350 secondsj
dumped schema for ./db.sqlite

By using sqlite3 you can check how the database changed.

The files can be found in my GitHub repo soda-pop-example.