darkstar
darkstar

Reputation: 988

How to create foreign keys in gorm?

So I have two tables in application: users and posts. I'd like to implement a liking functionality where a user can like a post. To do this I created the following table:

type Like struct {
    PostId    string    `json:"post_id"`
    UserId    string    `json:"user_id"`
    CreatedAt time.Time `json:"created_at"`
}

My questions is how can I make it so when I AutoMigrate the Like model, foreign keys are setup automatically?

I have tried using the gorm:"foreignKey:Post" and gorm:"foreignKey:User" struct tags in their respective spots but they don't do anything.

How could I get this to work? Thank you!

Upvotes: 4

Views: 2265

Answers (1)

Shahriar Ahmed
Shahriar Ahmed

Reputation: 615

As you are not following conventions (i.e. Id instead of ID, PostId instead of PostID) in naming you need to explicitly tell gorm which is the foreign key and referred to which property.

Here is the snippet. Github Link

Reference:

  1. Belongs To
  2. Has Many
package storage2

import (
    "log"

    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
    "gorm.io/gorm/logger"
)

type Post struct {
    Body   string `gorm:"type:text"`
    Id     string `gorm:"type:uuid;primary_key"`
    Likes  []Like `gorm:"foreignkey:PostId;references:Id"`
    User   User   `gorm:"foreignkey:UserId;references:Id"`
    UserId string
}

type Like struct {
    Id     string `gorm:"type:uuid;primary_key"`
    PostId string `gorm:"type:uuid;not null"`
    User   User   `gorm:"foreignkey:UserId;references:Id"`
    UserId string
}

type User struct {
    Id   string `gorm:"type:uuid;primary_key"`
    Name string
}

func GormTest() {
    db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
        Logger: logger.Default.LogMode(logger.Info),
    })
    if err != nil {
        log.Fatal("could not open database")
    }
    err = db.AutoMigrate(&User{}, &Post{}, &Like{})
    if err != nil {
        log.Fatal("could not migrate database")
    }
    createTestData(db)
    fetchData(db)
}

func createTestData(db *gorm.DB) {
    users := []User{
        {Id: "0b83313d-1f85-4093-8621-efd2f21419d3", Name: "Shahriar"},
        {Id: "bddd6566-bcd2-4ad1-8eb9-65a23f5a9856", Name: "John"},
        {Id: "663c1328-dce2-4527-aecb-7fc478c229c2", Name: "Durand"}}
    err := db.Create(&users).Error
    if err != nil {
        log.Println("failed to create user data")
    }
    like := Like{
        Id:     "45ba45fc-0900-4fcc-80dd-c394170b777b",
        UserId: users[0].Id,
    }
    post := Post{
        Id:     "4cebb4c7-d44e-4160-a2df-a06f43211d45",
        Body:   "Test Post",
        Likes:  []Like{like},
        UserId: users[1].Id,
    }
    err = db.Create(&post).Error
    if err != nil {
        log.Println("failed to crete post")
    }
}

func fetchData(db *gorm.DB) {
    post := Post{
        Id: "4cebb4c7-d44e-4160-a2df-a06f43211d45",
    }
    if err := db.Preload("Likes").First(&post).Error; err != nil {
        log.Println("failed to load post")
    }
    log.Println(post)
}

Upvotes: 4

Related Questions