Follow Golang naming specifications

This commit is contained in:
Luke Young 2016-07-05 20:32:15 -05:00
parent 5005a0cfae
commit 57819f3b34
7 changed files with 106 additions and 106 deletions

12
doc.go
View File

@ -13,26 +13,26 @@ the library in your jsonapi tags.
Example structs using a Blog > Post > Comment structure, Example structs using a Blog > Post > Comment structure,
type Blog struct { type Blog struct {
Id int `jsonapi:"primary,blogs"` ID int `jsonapi:"primary,blogs"`
Title string `jsonapi:"attr,title"` Title string `jsonapi:"attr,title"`
Posts []*Post `jsonapi:"relation,posts"` Posts []*Post `jsonapi:"relation,posts"`
CurrentPost *Post `jsonapi:"relation,current_post"` CurrentPost *Post `jsonapi:"relation,current_post"`
CurrentPostId int `jsonapi:"attr,current_post_id"` CurrentPostID int `jsonapi:"attr,current_post_id"`
CreatedAt time.Time `jsonapi:"attr,created_at"` CreatedAt time.Time `jsonapi:"attr,created_at"`
ViewCount int `jsonapi:"attr,view_count"` ViewCount int `jsonapi:"attr,view_count"`
} }
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"`
} }
type Comment struct { type Comment struct {
Id int `jsonapi:"primary,comments"` ID int `jsonapi:"primary,comments"`
PostId int `jsonapi:"attr,post_id"` PostID int `jsonapi:"attr,post_id"`
Body string `jsonapi:"attr,body"` Body string `jsonapi:"attr,body"`
} }

View File

@ -54,7 +54,7 @@ func showBlog(w http.ResponseWriter, r *http.Request) {
// ...fetch your blog... // ...fetch your blog...
intId, err := strconv.Atoi(id) intID, err := strconv.Atoi(id)
if err != nil { if err != nil {
http.Error(w, err.Error(), 500) http.Error(w, err.Error(), 500)
return return
@ -63,7 +63,7 @@ func showBlog(w http.ResponseWriter, r *http.Request) {
jsonapiRuntime := jsonapi.NewRuntime().Instrument("blogs.show") jsonapiRuntime := jsonapi.NewRuntime().Instrument("blogs.show")
// but, for now // but, for now
blog := testBlogForCreate(intId) blog := testBlogForCreate(intID)
w.WriteHeader(200) w.WriteHeader(200)
w.Header().Set("Content-Type", "application/vnd.api+json") w.Header().Set("Content-Type", "application/vnd.api+json")
@ -113,52 +113,52 @@ func main() {
func testBlogForCreate(i int) *Blog { func testBlogForCreate(i int) *Blog {
return &Blog{ return &Blog{
Id: 1 * i, ID: 1 * i,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
Posts: []*Post{ Posts: []*Post{
&Post{ &Post{
Id: 1 * i, ID: 1 * i,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1 * i, ID: 1 * i,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2 * i, ID: 2 * i,
Body: "bar", Body: "bar",
}, },
}, },
}, },
&Post{ &Post{
Id: 2 * i, ID: 2 * i,
Title: "Fuubar", Title: "Fuubar",
Body: "Bas", Body: "Bas",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1 * i, ID: 1 * i,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 3 * i, ID: 3 * i,
Body: "bas", Body: "bas",
}, },
}, },
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
Id: 1 * i, ID: 1 * i,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1 * i, ID: 1 * i,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2 * i, ID: 2 * i,
Body: "bar", Body: "bar",
}, },
}, },
@ -246,25 +246,25 @@ func exerciseHandler() {
} }
type Blog struct { type Blog struct {
Id int `jsonapi:"primary,blogs"` ID int `jsonapi:"primary,blogs"`
Title string `jsonapi:"attr,title"` Title string `jsonapi:"attr,title"`
Posts []*Post `jsonapi:"relation,posts"` Posts []*Post `jsonapi:"relation,posts"`
CurrentPost *Post `jsonapi:"relation,current_post"` CurrentPost *Post `jsonapi:"relation,current_post"`
CurrentPostId int `jsonapi:"attr,current_post_id"` CurrentPostID int `jsonapi:"attr,current_post_id"`
CreatedAt time.Time `jsonapi:"attr,created_at"` CreatedAt time.Time `jsonapi:"attr,created_at"`
ViewCount int `jsonapi:"attr,view_count"` ViewCount int `jsonapi:"attr,view_count"`
} }
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"`
} }
type Comment struct { type Comment struct {
Id int `jsonapi:"primary,comments"` ID int `jsonapi:"primary,comments"`
PostId int `jsonapi:"attr,post_id"` PostID int `jsonapi:"attr,post_id"`
Body string `jsonapi:"attr,body"` Body string `jsonapi:"attr,body"`
} }

View File

@ -14,8 +14,8 @@ type ManyPayload struct {
type Node struct { type Node struct {
Type string `json:"type"` Type string `json:"type"`
Id string `json:"id"` ID string `json:"id"`
ClientId string `json:"client-id,omitempty"` ClientID string `json:"client-id,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"` Attributes map[string]interface{} `json:"attributes,omitempty"`
Relationships map[string]interface{} `json:"relationships,omitempty"` Relationships map[string]interface{} `json:"relationships,omitempty"`
} }

View File

@ -62,7 +62,7 @@ func UnmarshalPayload(in io.Reader, model interface{}) error {
if payload.Included != nil { if payload.Included != nil {
includedMap := make(map[string]*Node) includedMap := make(map[string]*Node)
for _, included := range payload.Included { for _, included := range payload.Included {
key := fmt.Sprintf("%s,%s", included.Type, included.Id) key := fmt.Sprintf("%s,%s", included.Type, included.ID)
includedMap[key] = included includedMap[key] = included
} }
@ -83,7 +83,7 @@ func UnmarshalManyPayload(in io.Reader, t reflect.Type) ([]interface{}, error) {
if payload.Included != nil { if payload.Included != nil {
includedMap := make(map[string]*Node) includedMap := make(map[string]*Node)
for _, included := range payload.Included { for _, included := range payload.Included {
key := fmt.Sprintf("%s,%s", included.Type, included.Id) key := fmt.Sprintf("%s,%s", included.Type, included.ID)
includedMap[key] = included includedMap[key] = included
} }
@ -151,7 +151,7 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
} }
if annotation == "primary" { if annotation == "primary" {
if data.Id == "" { if data.ID == "" {
continue continue
} }
@ -161,9 +161,9 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
} }
if fieldValue.Kind() == reflect.String { if fieldValue.Kind() == reflect.String {
fieldValue.Set(reflect.ValueOf(data.Id)) fieldValue.Set(reflect.ValueOf(data.ID))
} else if fieldValue.Kind() == reflect.Int { } else if fieldValue.Kind() == reflect.Int {
id, err := strconv.Atoi(data.Id) id, err := strconv.Atoi(data.ID)
if err != nil { if err != nil {
er = err er = err
break break
@ -174,11 +174,11 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
break break
} }
} else if annotation == "client-id" { } else if annotation == "client-id" {
if data.ClientId == "" { if data.ClientID == "" {
continue continue
} }
fieldValue.Set(reflect.ValueOf(data.ClientId)) fieldValue.Set(reflect.ValueOf(data.ClientID))
} else if annotation == "attr" { } else if annotation == "attr" {
attributes := data.Attributes attributes := data.Attributes
if attributes == nil || len(data.Attributes) == 0 { if attributes == nil || len(data.Attributes) == 0 {
@ -371,7 +371,7 @@ func unmarshalNode(data *Node, model reflect.Value, included *map[string]*Node)
} }
func fullNode(n *Node, included *map[string]*Node) *Node { func fullNode(n *Node, included *map[string]*Node) *Node {
includedKey := fmt.Sprintf("%s,%s", n.Type, n.Id) includedKey := fmt.Sprintf("%s,%s", n.Type, n.ID)
if included != nil && (*included)[includedKey] != nil { if included != nil && (*included)[includedKey] != nil {
return (*included)[includedKey] return (*included)[includedKey]

View File

@ -10,7 +10,7 @@ import (
) )
type BadModel struct { type BadModel struct {
Id int `jsonapi:"primary"` ID int `jsonapi:"primary"`
} }
func TestMalformedTag(t *testing.T) { func TestMalformedTag(t *testing.T) {
@ -32,16 +32,16 @@ func TestUnmarshalInvalidJSON(t *testing.T) {
} }
} }
func TestUnmarshalSetsId(t *testing.T) { func TestUnmarshalSetsID(t *testing.T) {
in := samplePayloadWithId() in := samplePayloadWithID()
out := new(Blog) out := new(Blog)
if err := UnmarshalPayload(in, out); err != nil { if err := UnmarshalPayload(in, out); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if out.Id != 2 { if out.ID != 2 {
t.Fatalf("Did not set Id on dst interface") t.Fatalf("Did not set ID on dst interface")
} }
} }
@ -200,8 +200,8 @@ func TestUnmarshalNestedRelationshipsEmbedded_withClientIDs(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if model.Posts[0].ClientId == "" { if model.Posts[0].ClientID == "" {
t.Fatalf("ClientId not set from request on related record") t.Fatalf("ClientID not set from request on related record")
} }
} }
@ -234,7 +234,7 @@ func samplePayload() io.Reader {
"title": "Foo", "title": "Foo",
"body": "Bar", "body": "Bar",
}, },
ClientId: "1", ClientID: "1",
}, },
&Node{ &Node{
Type: "posts", Type: "posts",
@ -242,7 +242,7 @@ func samplePayload() io.Reader {
"title": "X", "title": "X",
"body": "Y", "body": "Y",
}, },
ClientId: "2", ClientID: "2",
}, },
}, },
}, },
@ -253,7 +253,7 @@ func samplePayload() io.Reader {
"title": "Bas", "title": "Bas",
"body": "Fuubar", "body": "Fuubar",
}, },
ClientId: "3", ClientID: "3",
Relationships: map[string]interface{}{ Relationships: map[string]interface{}{
"comments": &RelationshipManyNode{ "comments": &RelationshipManyNode{
Data: []*Node{ Data: []*Node{
@ -262,14 +262,14 @@ func samplePayload() io.Reader {
Attributes: map[string]interface{}{ Attributes: map[string]interface{}{
"body": "Great post!", "body": "Great post!",
}, },
ClientId: "4", ClientID: "4",
}, },
&Node{ &Node{
Type: "comments", Type: "comments",
Attributes: map[string]interface{}{ Attributes: map[string]interface{}{
"body": "Needs some work!", "body": "Needs some work!",
}, },
ClientId: "5", ClientID: "5",
}, },
}, },
}, },
@ -287,10 +287,10 @@ func samplePayload() io.Reader {
return out return out
} }
func samplePayloadWithId() io.Reader { func samplePayloadWithID() io.Reader {
payload := &OnePayload{ payload := &OnePayload{
Data: &Node{ Data: &Node{
Id: "2", ID: "2",
Type: "blogs", Type: "blogs",
Attributes: map[string]interface{}{ Attributes: map[string]interface{}{
"title": "New blog", "title": "New blog",
@ -308,66 +308,66 @@ func samplePayloadWithId() io.Reader {
func testModel() *Blog { func testModel() *Blog {
return &Blog{ return &Blog{
Id: 5, ID: 5,
ClientId: "1", ClientID: "1",
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
Posts: []*Post{ Posts: []*Post{
&Post{ &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2, ID: 2,
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },
&Post{ &Post{
Id: 2, ID: 2,
Title: "Fuubar", Title: "Fuubar",
Body: "Bas", Body: "Bas",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 3, ID: 3,
Body: "bas", Body: "bas",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2, ID: 2,
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },

View File

@ -178,15 +178,15 @@ func visitModelNode(model interface{}, included *map[string]*Node, sideload bool
if annotation == "primary" { if annotation == "primary" {
id := fieldValue.Interface() id := fieldValue.Interface()
switch nId := id.(type) { switch nID := id.(type) {
case string: case string:
node.Id = nId node.ID = nID
case int: case int:
node.Id = strconv.Itoa(nId) node.ID = strconv.Itoa(nID)
case int64: case int64:
node.Id = strconv.FormatInt(nId, 10) node.ID = strconv.FormatInt(nID, 10)
case uint64: case uint64:
node.Id = strconv.FormatUint(nId, 10) node.ID = strconv.FormatUint(nID, 10)
default: default:
er = ErrBadJSONAPIID er = ErrBadJSONAPIID
break break
@ -196,7 +196,7 @@ func visitModelNode(model interface{}, included *map[string]*Node, sideload bool
} else if annotation == "client-id" { } else if annotation == "client-id" {
clientID := fieldValue.String() clientID := fieldValue.String()
if clientID != "" { if clientID != "" {
node.ClientId = clientID node.ClientID = clientID
} }
} else if annotation == "attr" { } else if annotation == "attr" {
var omitEmpty bool var omitEmpty bool
@ -307,7 +307,7 @@ func visitModelNode(model interface{}, included *map[string]*Node, sideload bool
func toShallowNode(node *Node) *Node { func toShallowNode(node *Node) *Node {
return &Node{ return &Node{
Id: node.Id, ID: node.ID,
Type: node.Type, Type: node.Type,
} }
} }
@ -336,7 +336,7 @@ func appendIncluded(m *map[string]*Node, nodes ...*Node) {
included := *m included := *m
for _, n := range nodes { for _, n := range nodes {
k := fmt.Sprintf("%s,%s", n.Type, n.Id) k := fmt.Sprintf("%s,%s", n.Type, n.ID)
if _, hasNode := included[k]; hasNode { if _, hasNode := included[k]; hasNode {
continue continue

View File

@ -8,21 +8,21 @@ import (
) )
type Blog struct { type Blog struct {
Id int `jsonapi:"primary,blogs"` ID int `jsonapi:"primary,blogs"`
ClientId string `jsonapi:"client-id"` ClientID string `jsonapi:"client-id"`
Title string `jsonapi:"attr,title"` Title string `jsonapi:"attr,title"`
Posts []*Post `jsonapi:"relation,posts"` Posts []*Post `jsonapi:"relation,posts"`
CurrentPost *Post `jsonapi:"relation,current_post"` CurrentPost *Post `jsonapi:"relation,current_post"`
CurrentPostId int `jsonapi:"attr,current_post_id"` CurrentPostID int `jsonapi:"attr,current_post_id"`
CreatedAt time.Time `jsonapi:"attr,created_at"` CreatedAt time.Time `jsonapi:"attr,created_at"`
ViewCount int `jsonapi:"attr,view_count"` ViewCount int `jsonapi:"attr,view_count"`
} }
type Post struct { type Post struct {
Blog Blog
Id int `jsonapi:"primary,posts"` ID int `jsonapi:"primary,posts"`
BlogId int `jsonapi:"attr,blog_id"` BlogID int `jsonapi:"attr,blog_id"`
ClientId string `jsonapi:"client-id"` ClientID string `jsonapi:"client-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"`
@ -30,15 +30,15 @@ type Post struct {
} }
type Comment struct { type Comment struct {
Id int `jsonapi:"primary,comments"` ID int `jsonapi:"primary,comments"`
ClientId string `jsonapi:"client-id"` ClientID string `jsonapi:"client-id"`
PostId int `jsonapi:"attr,post_id"` PostID int `jsonapi:"attr,post_id"`
Body string `jsonapi:"attr,body"` Body string `jsonapi:"attr,body"`
} }
func TestHasPrimaryAnnotation(t *testing.T) { func TestHasPrimaryAnnotation(t *testing.T) {
testModel := &Blog{ testModel := &Blog{
Id: 5, ID: 5,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
@ -60,14 +60,14 @@ func TestHasPrimaryAnnotation(t *testing.T) {
t.Fatalf("type should have been blogs, got %s", data.Type) t.Fatalf("type should have been blogs, got %s", data.Type)
} }
if data.Id != "5" { if data.ID != "5" {
t.Fatalf("Id not transfered") t.Fatalf("ID not transfered")
} }
} }
func TestSupportsAttributes(t *testing.T) { func TestSupportsAttributes(t *testing.T) {
testModel := &Blog{ testModel := &Blog{
Id: 5, ID: 5,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
@ -95,7 +95,7 @@ func TestSupportsAttributes(t *testing.T) {
func TestOmitsZeroTimes(t *testing.T) { func TestOmitsZeroTimes(t *testing.T) {
testModel := &Blog{ testModel := &Blog{
Id: 5, ID: 5,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Time{}, CreatedAt: time.Time{},
} }
@ -154,7 +154,7 @@ func TestRelations(t *testing.T) {
} }
func TestNoRelations(t *testing.T) { func TestNoRelations(t *testing.T) {
testModel := &Blog{Id: 1, Title: "Title 1", CreatedAt: time.Now()} testModel := &Blog{ID: 1, Title: "Title 1", CreatedAt: time.Now()}
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
if err := MarshalOnePayload(out, testModel); err != nil { if err := MarshalOnePayload(out, testModel); err != nil {
@ -174,45 +174,45 @@ func TestNoRelations(t *testing.T) {
func TestMarshalMany(t *testing.T) { func TestMarshalMany(t *testing.T) {
data := []interface{}{ data := []interface{}{
&Blog{ &Blog{
Id: 5, ID: 5,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
Posts: []*Post{ Posts: []*Post{
&Post{ &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
}, },
&Post{ &Post{
Id: 2, ID: 2,
Title: "Fuubar", Title: "Fuubar",
Body: "Bas", Body: "Bas",
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
}, },
}, },
&Blog{ &Blog{
Id: 6, ID: 6,
Title: "Title 2", Title: "Title 2",
CreatedAt: time.Now(), CreatedAt: time.Now(),
Posts: []*Post{ Posts: []*Post{
&Post{ &Post{
Id: 3, ID: 3,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
}, },
&Post{ &Post{
Id: 4, ID: 4,
Title: "Fuubar", Title: "Fuubar",
Body: "Bas", Body: "Bas",
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
Id: 4, ID: 4,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
}, },
@ -238,65 +238,65 @@ func TestMarshalMany(t *testing.T) {
func testBlog() *Blog { func testBlog() *Blog {
return &Blog{ return &Blog{
Id: 5, ID: 5,
Title: "Title 1", Title: "Title 1",
CreatedAt: time.Now(), CreatedAt: time.Now(),
Posts: []*Post{ Posts: []*Post{
&Post{ &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2, ID: 2,
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },
&Post{ &Post{
Id: 2, ID: 2,
Title: "Fuubar", Title: "Fuubar",
Body: "Bas", Body: "Bas",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 3, ID: 3,
Body: "bas", Body: "bas",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },
}, },
CurrentPost: &Post{ CurrentPost: &Post{
Id: 1, ID: 1,
Title: "Foo", Title: "Foo",
Body: "Bar", Body: "Bar",
Comments: []*Comment{ Comments: []*Comment{
&Comment{ &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
&Comment{ &Comment{
Id: 2, ID: 2,
Body: "bar", Body: "bar",
}, },
}, },
LatestComment: &Comment{ LatestComment: &Comment{
Id: 1, ID: 1,
Body: "foo", Body: "foo",
}, },
}, },