Your Question

I have the following structures

type Contact struct {
    gorm.Model
    Phone     string          `json:"phone_number,omitempty"`
    Cellphone string          `json:"cellphone,omitempty"`
    Email     string          `json:"email,omitempty"`
    Linkedin  string          `json:"linkedin,omitempty"`
    Github    string          `json:"github,omitempty"`
    Other     json.RawMessage `json:"other,omitempty" gorm:"type:jsonb;default:'{}'"`
}

type User struct {
    gorm.Model
        FirstName       string
    // Foreign Keys
    ContactID int64    `json:"contact_id"`
    Contact   Contact `json:"contact"`
}

Whenever I run something like this:

curl --location --request PATCH 'http://localhost:8080/users' \
--header 'Content-Type: application/json' \
--data-raw '{
    "id": 1,
    "first_name": "David",
    "contact": {
        "id": 1,
        "phone_number": "555-5551"
    }
}'

I would expect something like this:

{
    "ID": 1,
    "first_name": "David", <--- Used to be John, so this is fine
    "contact_id": 1,
    "contact": {
        "ID": 1,
        "cellphone": "555-5550",
        "phone_number": "555-5551" <---- Before the PATCH this was null
        "email": "john@doe.com",
        "linkedin": "http://www.linkedin.com/john-doe",
        "other": "{test: test}"
    }
}

But the result after running that PATCH:

{
    "ID": 1,
    "first_name": "David", <--- Used to be John, so this is fine
    "contact_id": 1,
    "contact": {
        "ID": 1,
        "phone_number": "555-5551",
        "other": "{test: test}"
    }
}

For some weird reason I lost cellphone, email and linkedin data...

Someone told me that I should do something like this:

type Contact struct {
    gorm.Model
    Phone     string          `json:"phone_number,omitempty"`
    Cellphone string          `json:"cellphone,omitempty"`
    Email     string          `json:"email,omitempty"`
    Linkedin  string          `json:"linkedin,omitempty"`
    Github    string          `json:"github,omitempty"`
    Other     json.RawMessage `json:"other,omitempty" gorm:"type:jsonb;default:'{}'"`
        UserID    uint
}

type User struct {
    gorm.Model
        FirstName string
    // Foreign Keys
    ContactID int64    `json:"contact_id"`
    Contact   Contact `json:"contact"`
}

But this will create a one on one relation and I won't be able to create a User without a contact and that's no bueno, I need to be able to create a User without a contact.

On the server side I'm running the following go code:

r.db.GetDB().Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)

And I tried this as well:

r.db.GetDB().Preload("Contact").Updates(&user)

This is the debug result:

[1.818ms] [rows:1] UPDATE "schema"."users" SET "updated_at"='date',"first_name"='David',"contact_id"=1 WHERE "users"."deleted_at" IS NULL AND "id" = 1

Which is weird as well...

Edit: Debugging found this as well

[0.472ms] [rows:1] INSERT INTO "schema"."contacts" ("phone","cellphone","email","linkedin","github","created_at","updated_at","deleted_at","id") VALUES ('555-5551','','','','','2022-11-26 22:41:19.573','2022-11-26 22:41:19.573',NULL,1) ON CONFLICT ("id") DO UPDATE SET "updated_at"='2022-11-26 22:41:19.573',"phone"="excluded"."phone","cellphone"="excluded"."cellphone","email"="excluded"."email","linkedin"="excluded"."linkedin","github"="excluded"."github","deleted_at"="excluded"."deleted_at" RETURNING "other","id"

I don't know why that query is running... it should just update the values that changed instead of the whole struct

The document you expected this should be explained

https://gorm.io/docs/belongs_to.html

Expected answer

A solution lol