Part 5: Handling Migrations With Gorm in Go

Keith wachira
Keith wachira
Lead Engineer at Ndunyu.
Mar 23, 2019 4 min read

This is the fifth tutorial in our series building a rest api in golang. In the last tutorial we learnt how one can define models using gorm.

However we did not persist this tables in our database.In this tutorial we are going to persist our tables and also create foreign keys for our tables.Gorm allow us to run migrations very easily.

You can find the code for this tutorial on Github

Open the migrations.go folder that we created in the migrations package and copy the following code.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package migrations

import (
	"food-delivery/database"
	"food-delivery/models"
)

func Migrate() {
   
	database.DBCon.AutoMigrate(models.User{}, models.Food{}, models.Address{}, models.OrderItems{}, models.Orders{})
	//we take the structs we created earlier to represent tables and create tables from them.
	//for example models.Users{} will create a table called users  with the fields we defined in that struct as the table fields.
	///if by any chance you ever add another struct you need to create a table for you can add it here.

}

intializing the migrations

Now what remains is to call our migrate method in our main.go so that we can initialize the migrations.

open the main.go and add the code below.

Note this is a continuation of the previous work from the fourth tutorial so you should add this code to the previous code.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main
import (
	"food-delivery/database"
	"food-delivery/migrations"

	_ "github.com/jinzhu/gorm/dialects/postgres"
	///this is the postgres driver remember to add the postgres driver

)
func main() {
	////initialize the database
	database.InitDB()
	migrations.Migrate()	///add this line to main.go
	////initialize the migrations
	//make sure when intializing the migrations the database is initialized
	///finally close the connection when you are done
	defer database.DBCon.Close()
}

If at this point you run the command go run main.go all the tables should be created in your delivery database.

Any time you make a change to this table the changes will be automatically applied to the database.

WARNING: AutoMigrate will ONLY create tables, missing columns and missing indexes, and WON’T change existing column’s type or delete unused columns to protect your data.

Adding Foreign Keys To Our Database In Gorm

In the last tutorial we discussed about database foreign keys.

In this tutorial we are going to apply them to our database,they will help us to query related data from our database.For example it will be very easy to query users orders once you have foreign keys.

We already defined all related tables in the previous tutorial so what we need to do here is just make sure they are persisted in the database.

Open the migrations.go and add the code below.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package migrations

import (
	"food-delivery/database"
	"food-delivery/models"
)

func Migrate() {

	database.DBCon.AutoMigrate(models.User{}, models.Food{}, models.Address{}, models.OrderItems{}, models.Orders{})
	
	///add this lines below that will add the foreign keys to the migrations.go
	database.DBCon.Model(&models.User{}).AddForeignKey("address_id", "address(id)", "CASCADE", "RESTRICT")
	///this will add the address_id foreign key to the user table from the address table
	database.DBCon.Model(&models.Orders{}).AddForeignKey("user_id", "users(id)", "CASCADE", "RESTRICT")
		///this will add the user_id foreign key to the order table which is related to user table
	database.DBCon.Model(&models.OrderItems{}).AddForeignKey("order_id", "orders(id)", "CASCADE", "RESTRICT")
	///Cascade means whenever we delete the parent record the child  record should be deleted
	///that is for example if we delete a user all his orders shall be deleted
	database.DBCon.Model(&models.OrderItems{}).AddForeignKey("food_id", "foods(id)", "CASCADE", "RESTRICT")

}

With that we are done with our database and we are now ready for action.

Conclusion

Gorm makes it very easy for us to run migrations.However for more complicated migrations you may use gormigrate which we will cover later in this tutorial.

Now we are done with the most important part of our project,that is the database.If you make your database well the other processes will be very easy.

In the next chapter we are going to start making the handlers,that is we are going to start registering users and login in them in our application.We are also going to start adding food.

Make sure to leave a comment of anything you may need more clarification or how we can make this tutorial more helpful to other people who read it.See you in the next tutorial.

Cheers Happy Coding!!!!!