GORM foreign keys without embedded struct - go

So, using GORM I realize that to use foreign keys, I have to embed the struct in another struct, otherwise gorm won't recognize the relationship like this:
type People struct {
ID int
Name string
Card []Card
}
type Card struct {
ID int
Name string
PeopleID int
}
But, i don't actually want this embeding system. For me, it becomes more troublesome to do sanitization when developing REST apis. So, is there a way to tell GORM about the relationship without actually having to have an embedded struct onto another? Like:
type People struct {
ID int
Name string
//No `Card` object here
}
type Card struct {
ID int
Name string
PeopleID int `gorm:"foreignKey:People.ID` //Something like this
}

Related

How to access the fields of this struct in Golang

I'm new to Golang and I need to know how to access the value from a struct of the format:
type CurrentSkuList struct {
SubscriptionNumber string `json:"subscriptionNumber`
Quantity int `json:"quantity"`
SubscriptionProducts []struct {
ID int `json:"id"`
ActiveStartDate int `json:"activeStartDate"`
ActiveEndDate int `json:"activeEndDate"`
Status string `json:"status"`
Sku string `json:"sku"`
ChildIDs []int `json:"childrenIds"`
} `json:"subscriptionProducts"`
}
For example, if I have a variable currentSkus of type CurrentSkuList and I need to access only Sku and Status values, is there a way to do something like:
currentSkus.SubscriptionProducts.Sku?
EDIT! When I try to access currentSkus.Quantity I get a compiler error undefined (type []util.CurrentSkuList has no field or method Quantity).
Yeah, there is a way. You can access by the . syntax you proposed. In this case, CurrentSkuList is returning an slice of SubscriptionProduct, you know that because of the [] struct part. Then you would have to access to the data this way:
currentSkus.SubscriptionProducts[index].Sku

Mapping one type to another

Let's say I have the following types.
type Contract struct {
Id string `json:"id" gorm:"column:uuid"`
Name string `json:"name" gorm:"column:name"`
Description string `json:"descr" gorm:"column:descr"`
ContractTypeId int `json:"contract_type_id" gorm:"column:contract_type_id"`
}
type ContractModel struct {
Id string `json:"id" gorm:"column:uuid"`
Name string `json:"name" gorm:"column:name"`
Description string `json:"descr" gorm:"column:descr"`
}
I have a SQL query using gorm to scan results into a contract object.
How can I map the values from the contract object into contractModel object?
I tried using the package go-automapper as such:
automapper.Map(contract, ContractModel{})
I want to drop the ContractTypeId.
Can I do this for multiple types in a list?
var contractModels []ContractModel
automapper.Map(contracts, &contractModels)
You can do either:
models := []ContractModel{}
automapper.Map(contracts, &models)
Or call automapper.Map in a loop:
models := make([]ContractModel, len(contracts))
for i := range contracts {
automapper.Map(contracts[i], &models[i])
}
You should be aware that automapper uses reflection behind the scenes and thus is much slower than straight forward non-polymorphic copying like #ThinkGoodly suggests. It's a totally fine solution if performance isn't top priority though.

Query with 'has one' association (one-to-one)

I'm playing a bit with Gorm while I'm trying to decide which ORM library fit the most for my needs.
Important to mention that I'm currently working with Sqlite.
Following the guide I created two structs:
type Color struct {
gorm.Model
UserID uint
Name string
}
//User struct define a basic user model
type User struct {
gorm.Model
Username string
Email string
FirstName string
LastName string
Password string
CreationDate time.Time
DOB time.Time
IgnoreMe int `gorm:"-"` // Ignore this field
Color Color `gorm:"foreignkey:ColorRefer"`
ColorRefer uint
}
when I'm creating a DB with
func CreateTables() {
user := dm.User{}
color := dm.Color{}
GormDB.CreateTable(&color)
GormDB.CreateTable(&user)
GormDB.Model(&user).AddForeignKey("ColorRefer", "colors(id)", "CASCADE", "CASCADE")
}
or with:
func CreateTables() {
GormDB.AutoMigrate(&dm.User{},&dm.Color{})
}
Sadly it's not working as I would of expect and create the foreign key automatically, but it's works when I do it manually.
My main problem is when I'm trying to query Users
//QueryByStructExample query users table by the struct non-zero (non-default) fields.
func QueryByStructExample(userStruct dm.User) []dm.User {
var results []dm.User
GormDB.Where(userStruct).Find(&results)
return results
}
I created the following function in a try to query users by email with the color property which is my color struct and I tried to play with a lot with the Model,Related and the Association functions, and nothing seems to work and (I'm avoiding to use join by purpose).
The end result is that it query my User but without the color (only with the ID in my colorRefer)
any suggestion?
Do you mean to preload the Color struct? If yes did you try to query it like that
GormDB.Preload('Color').Where(userStruct).Find(&results)

structs with multiple mapping notations

I have these two structs which represent the same entities (one comes from a Json file and the other from a DB)
type DriverJson struct {
ID int `json:"id"`
Name string `json:"name"`
}
type DriverOrm struct {
ID int `orm:"column(id);auto"`
Name string `orm:"column(name);size(255);null"`
}
I want to merge them into one Driver struct, how do I merge the mapping notations (orm:, json:)?
Thank you
As mentioned in the documentation of reflect.StructTag, by convention the value of a tag string is a space-separated key:"value" pairs, so simply:
type DriverJson struct {
ID int `json:"id" orm:"column(id);auto"`
Name string `json:"name" orm:"column(name);size(255);null`
}
For details, see What are the use(s) for tags in Go?

golang initilize inner struct object in nested structs

I have a nested struct
type Posts struct {
Id int
CreatedAt time.Time
Data struct {
Title string
UserName string
}
}
I want to create a Data object but var innerData Posts.Data doesn't seem to work. I don't want to create separate Data struct because I'm planning to avoid name collusions by having multiple structs which will have different inner structs named Data.
You can't. Posts.Data isn't the name of a type. The only thing you could do is var innerData struct{ ... }, which I'm sure you don't want to because then you would have repetition and need to make changes in two places. Otherwise, you have to give it a name. That name doesn't have to be Data, it can be PostData or something to make it unique.

Resources