Document Method Assign

This commit is contained in:
Jinzhu 2013-10-31 09:34:27 +08:00
parent 31b4baba6f
commit 0e692a13b1
5 changed files with 61 additions and 8 deletions

View File

@ -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?

View File

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

4
do.go
View File

@ -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("")

View File

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

View File

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