diff --git a/entity.go b/entity.go index d289e0a..a9c46cd 100644 --- a/entity.go +++ b/entity.go @@ -744,12 +744,13 @@ func (g *Goon) getStructKey(src interface{}) (key *datastore.Key, hasStringId bo } } } else if tagValue == "parent" { - if vf.Type() == reflect.TypeOf(&datastore.Key{}) { + dskeyType := reflect.TypeOf(&datastore.Key{}) + if vf.Type().ConvertibleTo(dskeyType) { if parent != nil { err = fmt.Errorf("goon: Only one field may be marked parent") return } - parent = vf.Interface().(*datastore.Key) + parent = vf.Convert(dskeyType).Interface().(*datastore.Key) } } } @@ -831,8 +832,10 @@ func (g *Goon) setStructKey(src interface{}, key *datastore.Key) error { if parentSet { return fmt.Errorf("goon: Only one field may be marked parent") } - if vf.Type() == reflect.TypeOf(&datastore.Key{}) { - vf.Set(reflect.ValueOf(key.Parent())) + dskeyType := reflect.TypeOf(&datastore.Key{}) + vfType := vf.Type() + if vfType.ConvertibleTo(dskeyType) { + vf.Set(reflect.ValueOf(key.Parent()).Convert(vfType)) parentSet = true } } diff --git a/goon_test.go b/goon_test.go index 89a3392..d0f03e8 100644 --- a/goon_test.go +++ b/goon_test.go @@ -2023,3 +2023,68 @@ func TestMultis(t *testing.T) { } } } + +type root struct { + Id int64 `datastore:"-" goon:"id"` + Data int +} + +type normalChild struct { + Id int64 `datastore:"-" goon:"id"` + Parent *datastore.Key `datastore:"-" goon:"parent"` + Data int +} + +type coolKey *datastore.Key + +type derivedChild struct { + Id int64 `datastore:"-" goon:"id"` + Parent coolKey `datastore:"-" goon:"parent"` + Data int +} + +func TestParents(t *testing.T) { + c, err := aetest.NewContext(nil) + if err != nil { + t.Fatalf("Could not start aetest - %v", err) + } + defer c.Close() + n := FromContext(c) + + r := &root{1, 10} + rootKey, err := n.Put(r) + if err != nil { + t.Fatalf("couldn't Put(%+v)", r) + } + + // Put exercises both get and set, since Id is uninitialized + nc := &normalChild{0, rootKey, 20} + nk, err := n.Put(nc) + if err != nil { + t.Fatalf("couldn't Put(%+v)", nc) + } + if nc.Parent == rootKey { + t.Fatalf("derived parent key pointer value didn't change") + } + if !(*datastore.Key)(nc.Parent).Equal(rootKey) { + t.Fatalf("parent of key not equal '%s' v '%s'! ", (*datastore.Key)(nc.Parent), rootKey) + } + if !nk.Parent().Equal(rootKey) { + t.Fatalf("parent of key not equal '%s' v '%s'! ", nk, rootKey) + } + + dc := &derivedChild{0, (coolKey)(rootKey), 12} + dk, err := n.Put(dc) + if err != nil { + t.Fatalf("couldn't Put(%+v)", dc) + } + if dc.Parent == rootKey { + t.Fatalf("derived parent key pointer value didn't change") + } + if !(*datastore.Key)(dc.Parent).Equal(rootKey) { + t.Fatalf("parent of key not equal '%s' v '%s'! ", (*datastore.Key)(dc.Parent), rootKey) + } + if !dk.Parent().Equal(rootKey) { + t.Fatalf("parent of key not equal '%s' v '%s'! ", dk, rootKey) + } +}