From 31b4baba6f838701ecd0e251e23f97b005f5e9a4 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Thu, 31 Oct 2013 08:29:57 +0800 Subject: [PATCH] Make Updates accept struct other than map[string]interface{} --- README.md | 6 ++++++ chain.go | 2 +- do.go | 16 ++++++++++++++-- gorm_test.go | 5 ++++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 82841d7f..1352a8bb 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,12 @@ db.Table("users").Where(10).Updates(map[string]interface{}{"name": "hello", "age //// update users set name='hello', age=18 where id = 10; db.Table("users").Updates(map[string]interface{}{"name": "hello", "age": 18}) //// update users set name='hello', age=18; +db.Find(&users).Updates(User{Name: "hello", Age: 18}) +//// update users set name='hello', age=18; +db.First(&user, 20).Updates(User{Name: "hello", Age: 18}) +//// update users set name='hello', age=18 where id = 20; +//// object user's value would be reflected by the Updates also, +//// so you don't need to refetch the user from database // Soft Delete // For those struct have DeletedAt field, they will get soft delete ability automatically! diff --git a/chain.go b/chain.go index ecdd8247..e370fca9 100644 --- a/chain.go +++ b/chain.go @@ -157,7 +157,7 @@ func (s *Chain) Update(column string, value interface{}) *Chain { return s.Updates(map[string]interface{}{column: value}, true) } -func (s *Chain) Updates(values map[string]interface{}, ignore_protected_attrs ...bool) *Chain { +func (s *Chain) Updates(values interface{}, ignore_protected_attrs ...bool) *Chain { s.do(s.value).setUpdateAttrs(values, ignore_protected_attrs...).update() return s } diff --git a/do.go b/do.go index 5f19927d..a8bf9900 100644 --- a/do.go +++ b/do.go @@ -146,8 +146,20 @@ func (s *Do) create() { return } -func (s *Do) setUpdateAttrs(values map[string]interface{}, ignore_protected_attrs ...bool) *Do { - s.updateAttrs = values +func (s *Do) setUpdateAttrs(values interface{}, ignore_protected_attrs ...bool) *Do { + switch values.(type) { + case map[string]interface{}: + s.updateAttrs = values.(map[string]interface{}) + case interface{}: + m := &Model{data: values, driver: s.driver} + fields := m.columnsHasValue("") + + s.updateAttrs = make(map[string]interface{}, len(fields)) + for _, field := range fields { + s.updateAttrs[field.DbName] = field.Value + } + } + s.ignoreProtectedAttrs = len(ignore_protected_attrs) > 0 && ignore_protected_attrs[0] return s } diff --git a/gorm_test.go b/gorm_test.go index fe48fbc5..fa99d5be 100644 --- a/gorm_test.go +++ b/gorm_test.go @@ -778,7 +778,10 @@ func TestUpdates(t *testing.T) { updated_at2 := product2.UpdatedAt var product3 Product - db.First(&product3, product2.Id).Updates(map[string]interface{}{"code": "edf", "price": 100}) + db.First(&product3, product2.Id).Updates(Product{Code: "edf", Price: 100}) + if product3.Code != "edf" || product3.Price != 100 { + t.Errorf("Object should be updated also with update attributes") + } if updated_at2.Format(time.RFC3339Nano) != product3.UpdatedAt.Format(time.RFC3339Nano) { t.Errorf("updated_at should not be updated if nothing really new")