bug fix: don't forget some included nodes

This commit is contained in:
Sam Woodard 2015-07-12 07:42:52 -07:00
parent a6c9e05c33
commit ca0304f527
3 changed files with 69 additions and 17 deletions

View File

@ -93,6 +93,26 @@ func TestUnmarshalNestedRelationships(t *testing.T) {
} }
} }
func TestUnmarshalRelationshipsSerializedEmbedded(t *testing.T) {
out := sampleSerializedEmbeddedTestModel()
if out.CurrentPost == nil {
t.Fatalf("Current post was not materialized")
}
if out.CurrentPost.Title != "Foo" || out.CurrentPost.Body != "Bar" {
t.Fatalf("Attributes were not set")
}
if len(out.Posts) != 2 {
t.Fatalf("There should have been 2 posts")
}
if out.Posts[0].LatestComment.Body != "foo" {
t.Fatalf("The comment body was not set")
}
}
func TestUnmarshalNestedRelationshipsEmbedded(t *testing.T) { func TestUnmarshalNestedRelationshipsEmbedded(t *testing.T) {
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayloadEmbedded(out, testModel()); err != nil { if err := MarshalOnePayloadEmbedded(out, testModel()); err != nil {
@ -284,6 +304,10 @@ func testModel() *Blog {
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{
Id: 1,
Body: "foo",
},
}, },
&Post{ &Post{
Id: 2, Id: 2,
@ -299,6 +323,10 @@ func testModel() *Blog {
Body: "bas", Body: "bas",
}, },
}, },
LatestComment: &Comment{
Id: 1,
Body: "foo",
},
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
@ -315,6 +343,10 @@ func testModel() *Blog {
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{
Id: 1,
Body: "foo",
},
}, },
} }
} }
@ -327,3 +359,14 @@ func samplePayloadWithSideloaded() io.Reader {
return out return out
} }
func sampleSerializedEmbeddedTestModel() *Blog {
out := bytes.NewBuffer(nil)
MarshalOnePayloadEmbedded(out, testModel())
blog := new(Blog)
UnmarshalPayload(out, blog)
return blog
}

View File

@ -161,12 +161,12 @@ func visitModelNode(model interface{}, sideload bool) (*Node, []*Node, error) {
} }
if isSlice { if isSlice {
relationship, err := visitModelNodeRelationships(args[1], fieldValue, sideload) relationship, incl, err := visitModelNodeRelationships(args[1], fieldValue, sideload)
d := relationship[args[1]].Data d := relationship.Data
if err == nil { if err == nil {
if sideload { if sideload {
included = append(included, d...) included = append(included, incl...)
shallowNodes := make([]*Node, 0) shallowNodes := make([]*Node, 0)
for _, node := range d { for _, node := range d {
shallowNodes = append(shallowNodes, toShallowNode(node)) shallowNodes = append(shallowNodes, toShallowNode(node))
@ -174,17 +174,18 @@ func visitModelNode(model interface{}, sideload bool) (*Node, []*Node, error) {
node.Relationships[args[1]] = &RelationshipManyNode{Data: shallowNodes} node.Relationships[args[1]] = &RelationshipManyNode{Data: shallowNodes}
} else { } else {
node.Relationships[args[1]] = &RelationshipManyNode{Data: d} node.Relationships[args[1]] = relationship
} }
} else { } else {
er = err er = err
return false return false
} }
} else { } else {
relationship, inc, err := visitModelNode(fieldValue.Interface(), sideload) relationship, incl, err := visitModelNode(fieldValue.Interface(), sideload)
if err == nil { if err == nil {
if sideload { if sideload {
included = append(included, inc...) included = append(included, incl...)
included = append(included, relationship)
node.Relationships[args[1]] = &RelationshipOneNode{Data: toShallowNode(relationship)} node.Relationships[args[1]] = &RelationshipOneNode{Data: toShallowNode(relationship)}
} else { } else {
node.Relationships[args[1]] = &RelationshipOneNode{Data: relationship} node.Relationships[args[1]] = &RelationshipOneNode{Data: relationship}
@ -218,22 +219,29 @@ func toShallowNode(node *Node) *Node {
} }
} }
func visitModelNodeRelationships(relationName string, models reflect.Value, sideload bool) (map[string]*RelationshipManyNode, error) { func visitModelNodeRelationships(relationName string, models reflect.Value, sideload bool) (*RelationshipManyNode, []*Node, error) {
m := make(map[string]*RelationshipManyNode)
nodes := make([]*Node, 0) nodes := make([]*Node, 0)
var included []*Node
if sideload {
included = make([]*Node, 0)
}
for i := 0; i < models.Len(); i++ { for i := 0; i < models.Len(); i++ {
node, _, err := visitModelNode(models.Index(i).Interface(), sideload) node, incl, err := visitModelNode(models.Index(i).Interface(), sideload)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
nodes = append(nodes, node) nodes = append(nodes, node)
included = append(included, incl...)
} }
m[relationName] = &RelationshipManyNode{Data: nodes} included = append(included, nodes...)
return m, nil n := &RelationshipManyNode{Data: nodes}
return n, included, nil
} }
func deleteNode(a []*Node, i int) []*Node { func deleteNode(a []*Node, i int) []*Node {

View File

@ -19,11 +19,12 @@ type Blog struct {
} }
type Post struct { type Post struct {
Id int `jsonapi:"primary,posts"` Id int `jsonapi:"primary,posts"`
BlogId int `jsonapi:"attr,blog_id"` BlogId int `jsonapi:"attr,blog_id"`
Title string `jsonapi:"attr,title"` Title string `jsonapi:"attr,title"`
Body string `jsonapi:"attr,body"` Body string `jsonapi:"attr,body"`
Comments []*Comment `jsonapi:"relation,comments"` Comments []*Comment `jsonapi:"relation,comments"`
LatestComment *Comment `jsonapi:"relation,latest_comment"`
} }
type Comment struct { type Comment struct {