Add update tag.

This attempts to address a concern in issues #202 and #192.

It adds a gorm field tag that allows one to specify that the tagged field should always be updated.
This commit is contained in:
Robert B Gordon 2014-09-06 01:09:39 -05:00
parent 58ff124210
commit 5b88384bd0
5 changed files with 59 additions and 4 deletions

View File

@ -16,7 +16,7 @@ func CommitOrRollbackTransaction(scope *Scope) {
func SaveBeforeAssociations(scope *Scope) { func SaveBeforeAssociations(scope *Scope) {
for _, field := range scope.Fields() { for _, field := range scope.Fields() {
if !field.IsBlank && !field.IsIgnored { if field.AlwaysUpdate || !field.IsBlank && !field.IsIgnored {
relationship := field.Relationship relationship := field.Relationship
if relationship != nil && relationship.Kind == "belongs_to" { if relationship != nil && relationship.Kind == "belongs_to" {
value := field.Field value := field.Field
@ -42,7 +42,7 @@ func SaveBeforeAssociations(scope *Scope) {
func SaveAfterAssociations(scope *Scope) { func SaveAfterAssociations(scope *Scope) {
for _, field := range scope.Fields() { for _, field := range scope.Fields() {
if !field.IsBlank && !field.IsIgnored { if field.AlwaysUpdate || !field.IsBlank && !field.IsIgnored {
relationship := field.Relationship relationship := field.Relationship
if relationship != nil && if relationship != nil &&
(relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") { (relationship.Kind == "has_one" || relationship.Kind == "has_many" || relationship.Kind == "many_to_many") {

View File

@ -23,6 +23,7 @@ type Field struct {
IsBlank bool IsBlank bool
IsIgnored bool IsIgnored bool
IsPrimaryKey bool IsPrimaryKey bool
AlwaysUpdate bool
} }
func (field *Field) IsScanner() bool { func (field *Field) IsScanner() bool {

View File

@ -304,7 +304,9 @@ func (scope *Scope) fieldFromStruct(fieldStruct reflect.StructField, withRelatio
if fieldStruct.Tag.Get(tagIdentifier) == "-" { if fieldStruct.Tag.Get(tagIdentifier) == "-" {
field.IsIgnored = true field.IsIgnored = true
} }
if _, ok := settings["UPDATE"]; ok {
field.AlwaysUpdate = true
}
if !field.IsIgnored { if !field.IsIgnored {
// parse association // parse association
if !indirectValue.IsValid() { if !indirectValue.IsValid() {

View File

@ -158,3 +158,55 @@ func TestUpdateColumn(t *testing.T) {
t.Errorf("updatedAt should not be updated with update column") t.Errorf("updatedAt should not be updated with update column")
} }
} }
func TestAlwaysUpdate(t *testing.T) {
type Always struct {
Id int64
Name string
Code string
Price int64 `gorm:"update"`
}
DB.DropTable(&Always{})
DB.CreateTable(&Always{})
obj1 := Always{Name: "obj1", Code: "code_1", Price: 10}
obj2 := Always{Name: "obj2", Code: "code_2", Price: 20}
// save initial
DB.Save(&obj1).Save(&obj2).UpdateColumn(map[string]interface{}{"code": "columnUpdate2"})
// fetch and verify
var obj3, obj4 Always
DB.First(&obj3, obj1.Id)
if obj3.Code != "code_1" || obj3.Price != 10 {
t.Errorf("obj1 was not saved correctly: expected: %#v got: %#v", obj1, obj3)
}
DB.First(&obj4, obj2.Id)
if obj4.Code != "columnUpdate2" || obj4.Price != 20 {
t.Errorf("obj2 was not saved correctly: expected: %#v got: %#v", obj2, obj4)
}
// now update via struct price should change to zero
obj5 := Always{Name: "obj2update", Code: "code_2"}
DB.Model(obj5).Updates(obj5)
var obj6 Always
DB.First(&obj6, obj2.Id)
if obj6.Code != "code_2" || obj6.Name != "obj2update" || obj6.Price != 0 {
t.Errorf("obj2 was not saved correctly: got: %#v", obj6)
}
var res []Always
DB.Find(&res)
if len(res) != 2 {
t.Error("Should have 2 objects")
}
// test where clause
var res1 []Always
DB.Where(Always{}).Find(&res1)
if len(res1) != 2 {
t.Error("Where() Should have 2 returned objects")
}
}

View File

@ -65,7 +65,7 @@ func convertInterfaceToMap(values interface{}) map[string]interface{} {
default: default:
scope := Scope{Value: values} scope := Scope{Value: values}
for _, field := range scope.Fields() { for _, field := range scope.Fields() {
if !field.IsBlank { if field.AlwaysUpdate || !field.IsBlank {
attrs[field.DBName] = field.Field.Interface() attrs[field.DBName] = field.Field.Interface()
} }
} }