Opinionated Framework - Models & Migrations
What you will learn
- How to set the database settings
- how create models and migrations
- how to use models to add, update, and delete records
Setup
Use our project from the morning lesson where our database settings should already be set and our database is created. Now let's get to work.
Models and Migrations
Creating a Migration
Migrations allow us to add, alter, delete tables from our database. To create a new migration run the command.
buffalo pop g model turtle
This will create an up and down file in the migrations folder, open up the up file and add this.
create_table("turtles") {
t.Column("id", "integer", {primary: true})
t.Column("name", "string", {"size": 100})
t.Column("age", "integer")
}
then run buffalo pop migrate
Our table has been created, now we need to create our model!
Creating Our Model
Now it's time to create a model so we can update and edit that table, our model was created earlier and can be found in the models folder (turtle.go). It will automatically create most of what we need, (a struct defining a Turtle, a Turtles type that is an array of Turtle, A String function to convert a turtle into a String, and functions where you can define any validations).
We just need to add our age and name properties to the struct. The tag on each property defines how the property is named in the database and in json (ca)
// Turtle is used by pop to map your turtles database table to your go code.
type Turtle struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Age int `json:"age" db:"age"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
Using the Model
Create a new file for our turtles routes actions/turtle.go and let's write all our usual crud routes and test as we go.
package actions
import (
"net/http"
"github.com/gobuffalo/buffalo"
"firstproject/models"
// "fmt"
"strconv"
)
// Create a Resource to Bundle standard CRUD Routes
type TurtlesResource struct{ }
// get request to /turtles return all turtles
func (u TurtlesResource) List(c buffalo.Context) error {
var turtles models.Turtles // declare variable to receive turtles
err := models.DB.All(&turtles) // store all turtles in the turtles variable
if err != nil {
return err
}
// send response
return c.Render(http.StatusOK, r.JSON(turtles))
}
// get request to /turtles/{turtle_id}
func (u TurtlesResource) Show(c buffalo.Context) error {
//grab the id from url param
id := c.Param("turtle_id")
// declare a variable to receive the turtle
turtle := models.Turtle{}
//Search for the Turtle
models.DB.Find(&turtle, id)
// return response
return c.Render(http.StatusOK, r.JSON(turtle))
}
// post request to /turtle to create new turtle from request body
func (u TurtlesResource) Create(c buffalo.Context) error {
// create a turtle to receive request body
turtle := &models.Turtle{}
// handle possible error when binding
if err := c.Bind(turtle); err != nil {
return err
}
// handle possible error when creating
err2 := models.DB.Create(turtle)
if (err2 != nil){
return err2
}
// We must return a response
return c.Render(http.StatusOK, r.JSON(turtle))
}
// put request to /turtle/{turtle_id} to update a Turtle
func (u TurtlesResource) Update(c buffalo.Context) error {
//grab the id from url param, convert from string
id, strerr := strconv.Atoi(c.Param("turtle_id"))
// handle possible error
if strerr != nil {
return strerr
}
// declare a variable to receive the turtle
turtle := &models.Turtle{}
// handle possible error when binding
if err := c.Bind(turtle); err != nil {
return err
}
// set the id
turtle.ID = id
//Search for the Turtle
models.DB.Update(turtle)
// return response
return c.Render(http.StatusOK, r.JSON(turtle))
}
// delete request to /turtles/{turtle_id}
func (u TurtlesResource) Destroy(c buffalo.Context) error {
//grab the id from url param, convert from string
id, strerr := strconv.Atoi(c.Param("turtle_id"))
// handle possible error
if strerr != nil {
return strerr
}
// declare a variable to receive the turtle
turtle := &models.Turtle{ID: id}
//delete turtle
err := models.DB.Destroy(turtle)
// handle possible error
if err != nil {
return err
}
return c.Render(http.StatusOK, r.JSON(map[string]string{"Done": "Turtle Destroyed"}))
}
Add the routes to go with them in app.go
// A Resource routes creates all the crud routes on one line
app.Resource("/turtles", TurtlesResource{})
Test out all the end points then let's get into lab.