Skip to content

Commit

Permalink
Merge pull request #30 from rabee-inc/feature/firestore_map
Browse files Browse the repository at this point in the history
Firestoreから取得時に、nilのMapを空Mapで補完されるように対応
  • Loading branch information
aikizoku authored Nov 17, 2023
2 parents afdecc7 + b9b0c0a commit 873e388
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 20 deletions.
5 changes: 3 additions & 2 deletions cloudfirestore/batch_getter_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ func (bg *batchGetter) commit(ctx context.Context) error {
log.Error(ctx, err)
return err
}
setDocByDst(dst, dsnp.Ref)
setEmptyBySlice(dst)
SetDocByDst(dst, dsnp.Ref)
SetEmptyBySlice(dst)
SetEmptyByMap(dst)
}
return nil
}
Expand Down
35 changes: 21 additions & 14 deletions cloudfirestore/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,9 @@ func Get(ctx context.Context, docRef *firestore.DocumentRef, dst any) (bool, err
log.Error(ctx, err)
return false, err
}
setDocByDst(dst, dsnp.Ref)
setEmptyBySlice(dst)
SetDocByDst(dst, dsnp.Ref)
SetEmptyBySlice(dst)
SetEmptyByMap(dst)
return true, nil
}

Expand Down Expand Up @@ -149,8 +150,9 @@ func GetMulti(ctx context.Context, cFirestore *firestore.Client, docRefs []*fire
return err
}
rrv := reflect.ValueOf(v)
setDocByDsts(rrv, rrt, dsnp.Ref)
setEmptyBySlices(rrv, rrt)
SetDocByDsts(rrv, rrt, dsnp.Ref)
SetEmptyBySlices(rrv, rrt)
SetEmptyByMaps(rrv, rrt)
rv.Set(reflect.Append(rv, rrv))
}
return nil
Expand Down Expand Up @@ -179,8 +181,9 @@ func GetByQuery(ctx context.Context, query firestore.Query, dst any) (bool, erro
log.Error(ctx, err)
return false, err
}
setDocByDst(dst, dsnp.Ref)
setEmptyBySlice(dst)
SetDocByDst(dst, dsnp.Ref)
SetEmptyBySlice(dst)
SetEmptyByMap(dst)
return true, nil
}

Expand Down Expand Up @@ -211,8 +214,9 @@ func ListByQuery(ctx context.Context, query firestore.Query, dsts any) error {
return err
}
rrv := reflect.ValueOf(v)
setDocByDsts(rrv, rrt, dsnp.Ref)
setEmptyBySlices(rrv, rrt)
SetDocByDsts(rrv, rrt, dsnp.Ref)
SetEmptyBySlices(rrv, rrt)
SetEmptyByMaps(rrv, rrt)
rv.Set(reflect.Append(rv, rrv))
}
return nil
Expand Down Expand Up @@ -250,8 +254,9 @@ func ListByQueryCursor(ctx context.Context, query firestore.Query, limit int, cu
return nil, err
}
rrv := reflect.ValueOf(v)
setDocByDsts(rrv, rrt, dsnp.Ref)
setEmptyBySlices(rrv, rrt)
SetDocByDsts(rrv, rrt, dsnp.Ref)
SetEmptyBySlices(rrv, rrt)
SetEmptyByMaps(rrv, rrt)
rv.Set(reflect.Append(rv, rrv))
lastDsnp = dsnp
}
Expand All @@ -267,7 +272,8 @@ func Create(ctx context.Context, colRef *firestore.CollectionRef, src any) error
if !ValidateCollectionRef(colRef) {
return errors.New("Invalid Collection Path: " + colRef.Path)
}
setEmptyBySlice(src)
SetEmptyBySlice(src)
SetEmptyByMap(src)
var docRef *firestore.DocumentRef
if tx := getContextTransaction(ctx); tx != nil {
id := stringutil.UniqueID()
Expand All @@ -293,7 +299,7 @@ func Create(ctx context.Context, colRef *firestore.CollectionRef, src any) error
return err
}
}
setDocByDst(src, docRef)
SetDocByDst(src, docRef)
return nil
}

Expand Down Expand Up @@ -332,7 +338,8 @@ func Set(ctx context.Context, docRef *firestore.DocumentRef, src any) error {
if !ValidateDocumentRef(docRef) {
return errors.New("Invalid Document Path: " + docRef.Path)
}
setEmptyBySlice(src)
SetEmptyBySlice(src)
SetEmptyByMap(src)
if tx := getContextTransaction(ctx); tx != nil {
err := tx.Set(docRef, src)
if err != nil {
Expand All @@ -352,7 +359,7 @@ func Set(ctx context.Context, docRef *firestore.DocumentRef, src any) error {
return err
}
}
setDocByDst(src, docRef)
SetDocByDst(src, docRef)
return nil
}

Expand Down
38 changes: 34 additions & 4 deletions cloudfirestore/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"cloud.google.com/go/firestore"
)

func setDocByDst(dst any, ref *firestore.DocumentRef) {
func SetDocByDst(dst any, ref *firestore.DocumentRef) {
rv := reflect.Indirect(reflect.ValueOf(dst))
rt := rv.Type()
if rt.Kind() == reflect.Struct {
Expand All @@ -25,7 +25,7 @@ func setDocByDst(dst any, ref *firestore.DocumentRef) {
}
}

func setDocByDsts(rv reflect.Value, rt reflect.Type, ref *firestore.DocumentRef) {
func SetDocByDsts(rv reflect.Value, rt reflect.Type, ref *firestore.DocumentRef) {
if rt.Kind() == reflect.Struct {
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
Expand All @@ -42,7 +42,7 @@ func setDocByDsts(rv reflect.Value, rt reflect.Type, ref *firestore.DocumentRef)
}
}

func setEmptyBySlice(dst any) {
func SetEmptyBySlice(dst any) {
rv := reflect.Indirect(reflect.ValueOf(dst))
rt := rv.Type()
if rt.Kind() == reflect.Struct {
Expand All @@ -58,7 +58,7 @@ func setEmptyBySlice(dst any) {
}
}

func setEmptyBySlices(rv reflect.Value, rt reflect.Type) {
func SetEmptyBySlices(rv reflect.Value, rt reflect.Type) {
if rt.Kind() == reflect.Struct {
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
Expand All @@ -71,3 +71,33 @@ func setEmptyBySlices(rv reflect.Value, rt reflect.Type) {
}
}
}

func SetEmptyByMap(dst any) {
rv := reflect.Indirect(reflect.ValueOf(dst))
rt := rv.Type()
if rt.Kind() == reflect.Struct {
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
if f.Type.Kind() == reflect.Map && rv.Field(i).Len() == 0 {
mp := reflect.MakeMap(f.Type)
m := reflect.Indirect(mp)
rv.Field(i).Set(m)
continue
}
}
}
}

func SetEmptyByMaps(rv reflect.Value, rt reflect.Type) {
if rt.Kind() == reflect.Struct {
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
if f.Type.Kind() == reflect.Map && rv.Elem().Field(i).Len() == 0 {
mp := reflect.MakeMap(f.Type)
m := reflect.Indirect(mp)
rv.Elem().Field(i).Set(m)
continue
}
}
}
}
141 changes: 141 additions & 0 deletions cloudfirestore/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// nolint
package cloudfirestore_test

import (
"reflect"
"testing"

"github.com/rabee-inc/go-pkg/cloudfirestore"
)

func Test_SetEmptyByMap(t *testing.T) {
type source struct {
Str string
Map map[string]*struct{}
}

type args struct {
source *source
}
type want struct {
isNil bool
}
type testCase struct {
name string
args args
want want
}

testCases := []testCase{
{
name: "補完される",
args: args{
source: &source{
Str: "test",
Map: nil,
},
},
want: want{
isNil: false,
},
},
{
name: "変化なし",
args: args{
source: &source{
Str: "test",
Map: map[string]*struct{}{},
},
},
want: want{
isNil: false,
},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
cloudfirestore.SetEmptyByMap(testCase.args.source)
if testCase.args.source.Map == nil {
if !testCase.want.isNil {
t.Errorf("testCase.args.source.Map is nil")
}
} else {
if testCase.want.isNil {
t.Errorf("testCase.args.source.Map is not nil")
}
}
})
}
}

func Test_SetEmptyByMaps(t *testing.T) {
type source struct {
Str string
Map map[string]*struct{}
}

type args struct {
sources []*source
}
type want struct {
isNil bool
}
type testCase struct {
name string
args args
want want
}

testCases := []testCase{
{
name: "補完される",
args: args{
sources: []*source{
{
Str: "test",
Map: nil,
},
},
},
want: want{
isNil: false,
},
},
{
name: "変化なし",
args: args{
sources: []*source{
{
Str: "test",
Map: map[string]*struct{}{},
},
},
},
want: want{
isNil: false,
},
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
dsts := []*source{}
rv := reflect.Indirect(reflect.ValueOf(dsts))
rrt := rv.Type().Elem().Elem()
for _, source := range testCase.args.sources {
rrv := reflect.ValueOf(source)
cloudfirestore.SetEmptyByMaps(rrv, rrt)
if source.Map == nil {
if !testCase.want.isNil {
t.Errorf("source.Map is nil")
}
} else {
if testCase.want.isNil {
t.Errorf("source.Map is not nil")
}
}
}
})
}
}

0 comments on commit 873e388

Please sign in to comment.