tolga
tolga

Reputation: 2830

Go migration doesn't create a foreign key

My first day with Go. I try to develop a migration mechanism with GORM within Revel.

These are my model structs:

type Role struct {
    gorm.Model
    Name string
}

type User struct {
    gorm.Model
    Name string
    Role Role  `gorm:"foreignkey:RoleIdForRole;association_foreignkey:Id"`
}

I simply automigrate both structs as follows, which work fine. I see tables called users and roles but users table doesn't have a field role_id or roleID

db.AutoMigrate(&models.Role{})
db.AutoMigrate(&models.User{})

What am I missing?

Upvotes: 1

Views: 2258

Answers (3)

Putra Fajar Hasanuddin
Putra Fajar Hasanuddin

Reputation: 1193

You need to set DisableForeignKeyConstraintWhenMigrating to false when opening connection.

user.go

type User struct {
    ID        uint      `json:"id" gorm:"primaryKey"`
    Name      string    `json:"name" gorm:"not null;type:varchar(255)"`
    Email     string    `json:"email" gorm:"not null;unique;type:varchar(255)"`
    Password  string    `json:"-" gorm:"not null;type:varchar(255)"`
    CreatedAt time.Time `json:"created_at,omitempty"`
    UpdatedAt time.Time `json:"updated_at,omitempty"`
    Tasks     []Task    `json:"tasks,omitempty" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}

func (u *User) TableName() string {
    return "users"
}

task.go

type TaskStatus string

const (
    TaskStatusPending TaskStatus = "pending"
    TaskStatusDone    TaskStatus = "done"
)

type Task struct {
    ID          uint       `json:"id" gorm:"primaryKey"`
    UserID      uint       `json:"user_id" gorm:"index:idx_user_id;not null"`
    Title       string     `json:"title" gorm:"type:varchar(255)"`
    Description string     `json:"description" gorm:"type:text"`
    Status      TaskStatus `json:"status" gorm:"type:varchar(50);default:pending"`
    CreatedAt   time.Time  `json:"created_at,omitempty"`
    UpdatedAt   time.Time  `json:"updated_at,omitempty"`
}

func (t *Task) TableName() string {
    return "tasks"
}

db.go

db, err = gorm.Open(postgres.Open(masterDSN), &gorm.Config{
    Logger: logger.Default.LogMode(loglevel),
    DisableForeignKeyConstraintWhenMigrating: false,
})
db.AutoMigrate(&model.User{}, &model.Task{})

Upvotes: 0

tolga
tolga

Reputation: 2830

I found a solution.

First of all, although Tim Brown's answer is a valid answer compatible with documentation, it doesn't work. As mentioned in many forum posts and github issues, GORM foreign key is not autogenerated as told in the documentation.

But this helps:

db.Model(&models.User{}).AddForeignKey("role_id", "roles(id)", "RESTRICT", "RESTRICT")

Shortly you need to set foreign keys just after migrating the tables.

Upvotes: 3

Tim Brown
Tim Brown

Reputation: 3241

You need a RoleID column, and if you name it that you wouldn't need to declare the foreignkey either.

type User struct {
    gorm.Model
    Name   string
    RoleID int `gorm:"column:RoleIdForRole"`
    Role   Role
}

See this page for more info

Upvotes: 1

Related Questions