Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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)
                That's documented and intended behaviour when using structs, you can use a map for properties that are affected by such a strange (IMO) design decision. gorm.io/docs/update.html#Update-Changed-Fields (note the comments)
– mkopriva
                Jun 18, 2019 at 16:34
                @mkopriva ohhh, Thanks, just noticed it. It says false are blank values of their types on struct usage
– 7urkm3n
                Jun 18, 2019 at 16:38

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:"-"`
                I prefer this method as I can still update my records with my models instead of using a map[string]interface{}.
– Munosphere
                Feb 26, 2022 at 12:49
                Another way is to set the default constraint to false. Although, you will have to explicitly specify the value for ShowDirectory. Either way, it's just terrible it works like that.
– Branislav Lazic
                Oct 28, 2022 at 12:35
                You can format your GORM attribute details as a bool type with the pointer as well, but its not necessary and this maps with and without.  gorm:"default:true;type:bool"
– Real.Cryptc
                Apr 18 at 17:33

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})

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

check documentation, it says false are blank values of their types and blank value is false always – 7urkm3n Aug 15, 2019 at 14:46 The problem is not if the model is defined correctly or not, the problem is that GORM doesn't work with boolean columns that are set as default true. P.S. The issue still exists in GORM +2 versions. – Branislav Lazic Oct 28, 2022 at 12:37

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

You said without a clear explanation and a best example and comparison, I just added more explanation. You know I faced the same issue and landed to this question but your answer didn’t help when I first saw your answer dint saw the actual difference at the first sight, trust me for few users my answer will help and that contains good explanation so I decided to write one more answer. Thanks for the answer – Narendranath Reddy Nov 4, 2020 at 3:57

Simply add `Select(*)

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

This way is much more simpler than others.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.