GORM doesnt update boolean field to false

Viewed 16981

On updates gorm doesnt update boolean type to false. By default it updates to true, but when i try to update to false not changes. I dont see any errors also. What can be the issue ?

type Attendee struct {
    ID             uint   `gorm:"primary_key" gorm:"AUTO_INCREMENT" json:"id,omitempty" mapstructure:"id" csv:"ID"`
    Email          string `json:"email,omitempty" mapstructure:"email" csv:"Email,required"`

    ShowDirectory  bool   `json:"show_directory,omitempty" gorm:"default:true" mapstructure:"show_directory" csv:"-"`
}


var attendee Attendee
// JSON.unmarshal lines here for the &attendee
if err := service.DB.Model(&attendee).Updates(Attendee{
        Email:         attendee.Email,
        ShowDirectory: false
}).Error; err != nil {
    return Attendee{}, err
}

Alternate Solution:

This works, but I am updating multiple attributies. So, I cant use this.

    att := Attendee{ID: 1}
    service.DB.Model(&att).Update("ShowDirectory", false)
6 Answers

As @mkopriva mentioned, by GORM Documentation

// Update attributes with `struct`, will only update non-zero fields
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 > 21:34:10' WHERE id = 111;

// Update attributes with `map`
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

NOTE When update with struct, GORM will only update non-zero fields, you might want to use map to update attributes or use Select to specify fields to update

Solved:

if err := service.DB.Model(&attendee).Updates(map[string]interface{}{
    "Email":          attendee.Email,
    "ShowDirectory": false
}).Error; err != nil {
    return Attendee{}, err
}

Another convenient way would be making that field as a pointer.

NOTE all fields having a zero value, like 0, '', false or other zero values, won’t be saved into the database but will use its default value. If you want to avoid this, consider using a pointer type or scanner/valuerLink

In your case, the model would look like:

type Attendee struct {
        ID             uint   `gorm:"primary_key" gorm:"AUTO_INCREMENT" json:"id,omitempty" mapstructure:"id" csv:"ID"`
        Email          string `json:"email,omitempty" mapstructure:"email" csv:"Email,required"`
    
        ShowDirectory  *bool   `json:"show_directory,omitempty" gorm:"default:true" mapstructure:"show_directory" csv:"-"`
}

You should write gorm type in your struct, something like this: gorm:"type:boolean; column:column_name" and for sure it will work!

As it's mentioned from the document, to set a falsy value you need to use map or select the columns you need.

When update with struct, GORM will only update non-zero fields, you might want to use map to update attributes or use Select to specify fields to update

// Select with Struct (select zero value fields)
db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
// UPDATE users SET name='new_name', age=0 WHERE id=111;

or you can select all columns:

// Select all fields (select all fields include zero value fields)
db.Model(&user).Select("*").Update(User{Name: "jinzhu", Role: "admin", Age: 0})

Please do not use go struct for updating the non-zero fields such as boolean:false

The below code will not update Active: false in your database and gorm simply ignore

db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

The below code will update the Active: false

db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

Use Map instead of go struct

Simply add `Select(*)

db.Model(&user).Select("*").Update(User{Name: "jinzhu", Role: "admin", Age: 0})

This way is much more simpler than others.

Related