From 0e692a13b12f1ebb1ba11e7584999f75f722f876 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Thu, 31 Oct 2013 09:34:27 +0800 Subject: [PATCH] Document Method Assign --- README.md | 36 ++++++++++++++++++++++++++++++++---- chain.go | 8 +++++++- do.go | 4 ++++ gorm_test.go | 19 +++++++++++++++++-- model.go | 2 +- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1352a8bb..913d307b 100644 --- a/README.md +++ b/README.md @@ -96,12 +96,23 @@ db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu", "age": 20}) // FirstOrInit With Attrs db.Where(User{Name: "noexisting_user"}).Attrs(User{Age: 20}).FirstOrInit(&user) //// user -> select * from users where name = 'noexisting_user'; -//// user -> User{Name: "noexisting_user", Age: 20} +//// If no record found, will assign the attrs to user, so user become: +//// User{Name: "noexisting_user", Age: 20} db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrInit(&user) //// user -> select * from users where name = 'jinzhu'; -//// user -> User{Id: 111, Name: "Jinzhu", Age: 18} -//// Do you notice the difference? The value in Attrs won't be used when search, -//// But is used to initalize the object if no record found +//// If found the user, will ingore the attrs: +//// User{Id: 111, Name: "Jinzhu", Age: 18} + +// FirstOrInit With Assign +db.Where(User{Name: "noexisting_user"}).Assign(User{Age: 20}).FirstOrInit(&user) +//// user -> select * from users where name = 'noexisting_user'; +//// If no record found, will assign the value to user, so user become: +//// User{Name: "noexisting_user", Age: 20} (same as FirstOrInit With Attrs) +//// user -> User{Name: "noexisting_user", Age: 20} +db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrInit(&user) +//// user -> select * from users where name = 'jinzhu'; +//// If found the user, will assign the value to user, so user become: (different with FirstOrInit With Attrs) +//// User{Id: 111, Name: "Jinzhu", Age: 20} // FirstOrCreate db.FirstOrCreate(&user, User{Name: "noexisting_user"}) @@ -114,9 +125,26 @@ db.FirstOrCreate(&user, map[string]interface{}{"name": "jinzhu", "age": 20}) // FirstOrCreate With Attrs db.Where(User{Name: "noexisting_user"}).Attrs(User{Age: 20}).FirstOrCreate(&user) //// user -> select * from users where name = 'noexisting_user'; +//// If not record found, will assing the attrs to the user first, then create it +//// Same as db.Where(User{Name: "noexisting_user"}).FirstOrCreate(&user).Update("age": 20), but one less sql //// user -> User{Id: 112, Name: "noexisting_user", Age: 20} db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 20}).FirstOrCreate(&user) //// user -> select * from users where name = 'jinzhu'; +//// If found any record, will ignore the attrs +//// user -> User{Id: 111, Name: "Jinzhu", Age: 18} + +// FirstOrCreate With Assign +db.Where(User{Name: "noexisting_user"}).Assign(User{Age: 20}).FirstOrCreate(&user) +//// user -> select * from users where name = 'noexisting_user'; +//// If not record found, will assing the value to the user first, then create it +//// user -> User{Id: 112, Name: "noexisting_user", Age: 20} (Same as FirstOrCreate With Attrs) +db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 20}).FirstOrCreate(&user) +//// user -> select * from users where name = 'jinzhu'; +//// If any record found, will assing the value to the user and update it +//// UPDATE users SET age=20 WHERE id = 111; +//// user -> User{Id: 111, Name: "Jinzhu", Age: 20} + + //// user -> User{Id: 111, Name: "Jinzhu", Age: 18} //// You must noticed that the Attrs is similar to FirstOrInit with Attrs, yes? diff --git a/chain.go b/chain.go index e370fca9..8a357df8 100644 --- a/chain.go +++ b/chain.go @@ -189,7 +189,9 @@ func (s *Chain) FirstOrInit(out interface{}, where ...interface{}) *Chain { s.do(out).where(where...).where(s.initAttrs).where(s.assignAttrs).initializeWithSearchCondition() s.deleteLastError() } else { - s.do(out).update() + if len(s.assignAttrs) > 0 { + s.do(out).setUpdateAttrs(s.assignAttrs).prepareUpdateAttrs() + } } return s } @@ -199,6 +201,10 @@ func (s *Chain) FirstOrCreate(out interface{}, where ...interface{}) *Chain { s.do(out).where(where...).where(s.initAttrs).where(s.assignAttrs).initializeWithSearchCondition() s.deleteLastError() s.Save(out) + } else { + if len(s.assignAttrs) > 0 { + s.do(out).setUpdateAttrs(s.assignAttrs).update() + } } return s } diff --git a/do.go b/do.go index a8bf9900..402b26f1 100644 --- a/do.go +++ b/do.go @@ -150,6 +150,10 @@ func (s *Do) setUpdateAttrs(values interface{}, ignore_protected_attrs ...bool) switch values.(type) { case map[string]interface{}: s.updateAttrs = values.(map[string]interface{}) + case []interface{}: + for _, value := range values.([]interface{}) { + s.setUpdateAttrs(value, ignore_protected_attrs...) + } case interface{}: m := &Model{data: values, driver: s.driver} fields := m.columnsHasValue("") diff --git a/gorm_test.go b/gorm_test.go index fa99d5be..c57d028d 100644 --- a/gorm_test.go +++ b/gorm_test.go @@ -889,12 +889,12 @@ func TestFindOrInitialize(t *testing.T) { db.Where(&User{Name: "find or init"}).Assign(User{Age: 44}).FirstOrInit(&user6) if user6.Name != "find or init" || user6.Id == 0 || user6.Age != 44 { - // t.Errorf("user should be found and updated with assigned attrs") + t.Errorf("user should be found and updated with assigned attrs") } } func TestFindOrCreate(t *testing.T) { - var user1, user2, user3, user4, user5 User + var user1, user2, user3, user4, user5, user6, user7 User db.Where(&User{Name: "find or create", Age: 33}).FirstOrCreate(&user1) if user1.Name != "find or create" || user1.Id == 0 || user1.Age != 33 { t.Errorf("user should be created with search value") @@ -915,8 +915,23 @@ func TestFindOrCreate(t *testing.T) { t.Errorf("user should be created with search value and attrs") } + db.Where(&User{Name: "find or create 4"}).Assign(User{Age: 44}).FirstOrCreate(&user4) + if user4.Name != "find or create 4" || user4.Id == 0 || user4.Age != 44 { + t.Errorf("user should be created with search value and assigned attrs") + } + db.Where(&User{Name: "find or create"}).Attrs(User{Age: 44}).FirstOrInit(&user5) if user5.Name != "find or create" || user5.Id == 0 || user5.Age != 33 { t.Errorf("user should be found and not initialized by Attrs") } + + db.Where(&User{Name: "find or create"}).Assign(User{Age: 44}).FirstOrCreate(&user6) + if user6.Name != "find or create" || user6.Id == 0 || user6.Age != 44 { + t.Errorf("user should be found and updated with assigned attrs") + } + + db.Where(&User{Name: "find or create"}).Find(&user7) + if user7.Name != "find or create" || user7.Id == 0 || user7.Age != 44 { + t.Errorf("user should be found and updated with assigned attrs") + } } diff --git a/model.go b/model.go index 037ac8d8..6887bd3d 100644 --- a/model.go +++ b/model.go @@ -139,10 +139,10 @@ func (m *Model) updatedColumnsAndValues(values map[string]interface{}) (map[stri if field.Interface() != value { switch field.Kind() { case reflect.Int, reflect.Int32, reflect.Int64: - field.SetInt(reflect.ValueOf(value).Int()) if field.Int() != reflect.ValueOf(value).Int() { results[key] = value } + field.SetInt(reflect.ValueOf(value).Int()) default: results[key] = value field.Set(reflect.ValueOf(value))