-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
generator & db: add db update tools for partial
- Loading branch information
1 parent
e23b6d5
commit 29b06ef
Showing
9 changed files
with
218 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package candishared | ||
|
||
import ( | ||
"reflect" | ||
"strings" | ||
) | ||
|
||
type partialUpdateOption struct { | ||
updateFields map[string]struct{} | ||
ignoreFields map[string]struct{} | ||
} | ||
|
||
// DBUpdateOptionFunc option func | ||
type DBUpdateOptionFunc func(*partialUpdateOption) | ||
|
||
// DBUpdateSetUpdatedFields option func | ||
func DBUpdateSetUpdatedFields(fields ...string) DBUpdateOptionFunc { | ||
return func(o *partialUpdateOption) { | ||
o.updateFields = make(map[string]struct{}) | ||
for _, field := range fields { | ||
o.updateFields[field] = struct{}{} | ||
} | ||
} | ||
} | ||
|
||
// DBUpdateSetIgnoredFields option func | ||
func DBUpdateSetIgnoredFields(fields ...string) DBUpdateOptionFunc { | ||
return func(o *partialUpdateOption) { | ||
o.ignoreFields = make(map[string]struct{}) | ||
for _, field := range fields { | ||
o.ignoreFields[field] = struct{}{} | ||
} | ||
} | ||
} | ||
|
||
// DBUpdateGORMExtractorKey struct tag key extractor for gorm model | ||
func DBUpdateGORMExtractorKey(structTag reflect.StructTag) string { | ||
return strings.Split(strings.TrimPrefix(structTag.Get("gorm"), "column:"), ";")[0] | ||
} | ||
|
||
// DBUpdateMongoExtractorKey struct tag key extractor for mongo model | ||
func DBUpdateMongoExtractorKey(structTag reflect.StructTag) string { | ||
return strings.TrimSuffix(structTag.Get("bson"), ",omitempty") | ||
} | ||
|
||
// DBUpdateTools for construct selected field to update | ||
type DBUpdateTools struct { | ||
KeyExtractorFunc func(structTag reflect.StructTag) string | ||
IgnoredFields []string | ||
} | ||
|
||
// ToMap method | ||
func (d DBUpdateTools) ToMap(data interface{}, opts ...DBUpdateOptionFunc) map[string]interface{} { | ||
var ( | ||
o partialUpdateOption | ||
updateFields = make(map[string]interface{}, 0) | ||
) | ||
|
||
for _, opt := range opts { | ||
opt(&o) | ||
} | ||
|
||
dataValue := reflect.ValueOf(data) | ||
dataType := reflect.TypeOf(data) | ||
if dataValue.Kind() == reflect.Ptr { | ||
dataValue = dataValue.Elem() | ||
dataType = dataType.Elem() | ||
} | ||
isPartial := len(o.updateFields) > 0 || len(o.ignoreFields) > 0 | ||
|
||
for i := 0; i < dataValue.NumField(); i++ { | ||
fieldValue := dataValue.Field(i) | ||
|
||
fieldType := dataType.Field(i) | ||
if fieldType.Anonymous { | ||
for k, v := range d.ToMap(fieldValue.Interface(), opts...) { | ||
updateFields[k] = v | ||
} | ||
continue | ||
} | ||
|
||
key := strings.TrimSuffix(fieldType.Tag.Get("json"), ",omitempty") | ||
if d.KeyExtractorFunc != nil { | ||
key = d.KeyExtractorFunc(fieldType.Tag) | ||
} | ||
|
||
val := fieldValue.Interface() | ||
if fieldValue.Kind() == reflect.Pointer { | ||
val = fieldValue.Elem().Interface() | ||
} | ||
|
||
if !isPartial { | ||
updateFields[key] = val | ||
continue | ||
} | ||
|
||
_, isFieldUpdated := o.updateFields[fieldType.Name] | ||
_, isFieldIgnored := o.ignoreFields[fieldType.Name] | ||
if (isFieldUpdated && len(o.updateFields) > 0) || (!isFieldIgnored && len(o.ignoreFields) > 0) { | ||
updateFields[key] = val | ||
} | ||
} | ||
|
||
for _, ignored := range d.IgnoredFields { | ||
delete(updateFields, ignored) | ||
} | ||
|
||
return updateFields | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package candishared | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/golangid/candi/candihelper" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestDBUpdateTools(t *testing.T) { | ||
|
||
type SubModel struct { | ||
Title string `gorm:"column:title" json:"title"` | ||
Profile string `gorm:"column:profile" json:"profile"` | ||
} | ||
|
||
type Model struct { | ||
ID int `gorm:"column:db_id;" json:"id"` | ||
Name *string `gorm:"column:db_name;" json:"name"` | ||
Address string `gorm:"column:db_address" json:"address"` | ||
SubModel | ||
} | ||
|
||
updated := DBUpdateTools{KeyExtractorFunc: DBUpdateGORMExtractorKey}.ToMap( | ||
&Model{ID: 1, Name: candihelper.ToStringPtr("01"), Address: "street", SubModel: SubModel{Title: "test"}}, | ||
DBUpdateSetUpdatedFields("ID", "Name", "Title"), | ||
) | ||
assert.Equal(t, 3, len(updated)) | ||
assert.Equal(t, 1, updated["db_id"]) | ||
assert.Equal(t, "01", updated["db_name"]) | ||
assert.Equal(t, "test", updated["title"]) | ||
|
||
updated = DBUpdateTools{}.ToMap( | ||
Model{ID: 1, Name: candihelper.ToStringPtr("01"), Address: "street", SubModel: SubModel{Title: "test"}}, | ||
DBUpdateSetIgnoredFields("ID", "Name", "Title"), | ||
) | ||
assert.Equal(t, 2, len(updated)) | ||
assert.Equal(t, "street", updated["address"]) | ||
|
||
updated = DBUpdateTools{}.ToMap( | ||
Model{ID: 1, Name: candihelper.ToStringPtr("01"), Address: "street", SubModel: SubModel{Title: "test"}}, | ||
) | ||
assert.Equal(t, 5, len(updated)) | ||
assert.Equal(t, "street", updated["address"]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.