1

I'm trying to create a belongs to relation between two database tables, using GORM, my code is the following:

type Shop struct {
    ID    uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
    Name  string    `json:"name" gorm:"not null" validate:"required"`
    City  string    `json:"city" gorm:"not null" validate:"required"`
    State string    `json:"state" gorm:"not null" validate:"required"`
}
type Employee struct {
    ID        uuid.UUID `json:"id" gorm:"primaryKey;type:uuid"`
    FirstName string    `json:"first_name" gorm:"not null" validate:"required"`
    LastName  string    `json:"last_name" gorm:"not null" validate:"required"`
    Email     string    `json:"email" gorm:"not null;unique" validate:"required,email"`
    Password  string    `json:"password" gorm:"not null" validate:"required"`
    Active    bool      `json:"active" gorm:"not null;default:false"`
    ShopId    uuid.UUID `json:"shop_id" gorm:"type:uuid"`
    Shop      Shop      `gorm:"foreignKey:ShopID"`
}

When I run the migrations, this error pops up:

[error] invalid field found for struct .../.../.../api/models.Employee's field Shop: define a valid foreign key for relations or implement the Valuer/Scanner interface

I've found some references using number primary keys and they seem to work fine, but I can't find any solution to work with uuids...

Marcelo
  • 585
  • 5
  • 13

1 Answers1

1

I'm not sure, but what I understand of the message error is that the type uuid.UUID doesn't have implemented the methods for the interfaces Valuer and Scanner.

You should create your own type UUID, which can be something like this:

type UUID uuid.UUID

func(id UUID) Value() (driver.Value, error) {   
    return id.String(), nil
}

func (id *UUID) Scan(value interface{}) error {
    dbID, ok := value.(string)
    if !ok {
        return errors.New("id scan: invalid value")
    }
    
    
    *e = uuid.MustParse(dbID)
    return nil
}

And use it on your struct's definitions:

type Shop struct {
    ID    UUID `json:"id" gorm:"primaryKey;type:uuid"`
    //...
}
Tecnologer
  • 458
  • 2
  • 11
  • 19
  • I'm using github.com/satori/go.uuid – Marcelo May 04 '22 at 19:24
  • Oh I see, that library has already implemented the Valuer/Scanner, so maybe you should use type `*Shop` on Employee – Tecnologer May 04 '22 at 19:38
  • and also try `gorm:"foreignKey:ShopId"` – Tecnologer May 04 '22 at 19:47
  • I just figured out that the problem is the lowercase "d" on "ShopId"... it should be "ShopID". I changed and now the migration worked. But after trying to create a new Employee, I got an error saying that the Shop name is required (because I have the validator rules on Shop struct too). I need to populate the Shop attribute on the Employee struct manually before the validation runs or should GORM do it automatically? – Marcelo May 04 '22 at 20:02
  • 1
    You need to populate Shop or change the type to `*Shop`, gorm will ignore it if detects is nil – Tecnologer May 04 '22 at 20:17
  • Great! It worked with `*Shop`! Thank you so much! – Marcelo May 04 '22 at 20:30