Skip to content

Commit

Permalink
Add an argument to CollectionOf() (#1232) (#1233)
Browse files Browse the repository at this point in the history
* Add an argument to CollectionOf()

It makes it possible to specify the collection identifier.

* Fix documents and a test description
  • Loading branch information
tchssk authored and raphael committed May 21, 2017
1 parent 2cdfcb7 commit b51fe1f
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 9 deletions.
59 changes: 51 additions & 8 deletions design/apidsl/media_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,31 @@ func Link(name string, view ...string) {
}
}

// CollectionOf creates a collection media type from its element media type. A collection media
// type represents the content of responses that return a collection of resources such as "list"
// actions. This function can be called from any place where a media type can be used.
// The resulting media type identifier is built from the element media type by appending the media
// type parameter "type" with value "collection".
func CollectionOf(v interface{}, apidsl ...func()) *design.MediaTypeDefinition {
// CollectionOf creates a collection media type from its element media type and an optional
// identifier. A collection media type represents the content of responses that return a collection
// of resources such as "list" actions. This function can be called from any place where a media
// type can be used.
//
// If an identifier isn't provided then the resulting media type identifier is built from the
// element media type by appending the media type parameter "type" with value "collection".
//
// Examples:
//
// // Define a collection media type using the default generated identifier
// // (e.g. "vnd.goa.bottle; type=collection" assuming the identifier of BottleMedia
// // is "vnd.goa.bottle") and the default views (i.e. inherited from the BottleMedia
// // views).
// var col = CollectionOf(BottleMedia)
//
// // Another collection media type using the same element media type but defining a
// // different default view.
// var col2 = CollectionOf(BottleMedia, "vnd.goa.bottle.alternate; type=collection;", func() {
// View("default", func() {
// Attribute("id")
// Attribute("name")
// })
// })
func CollectionOf(v interface{}, paramAndDSL ...interface{}) *design.MediaTypeDefinition {
var m *design.MediaTypeDefinition
var ok bool
m, ok = v.(*design.MediaTypeDefinition)
Expand Down Expand Up @@ -392,6 +411,10 @@ func CollectionOf(v interface{}, apidsl ...func()) *design.MediaTypeDefinition {
params["type"] = "collection"
}
id = mime.FormatMediaType(mediatype, params)
p, apidsl := parseCollectionOfDSL(paramAndDSL...)
if p != "" {
id = p
}
canonical := design.CanonicalIdentifier(id)
if mt, ok := design.GeneratedMediaTypes[canonical]; ok {
// Already have a type for this collection, reuse it.
Expand All @@ -403,8 +426,8 @@ func CollectionOf(v interface{}, apidsl ...func()) *design.MediaTypeDefinition {
// since the DSL may modify element type name via the TypeName function.
mt.TypeName = m.TypeName + "Collection"
mt.AttributeDefinition = &design.AttributeDefinition{Type: ArrayOf(m)}
if len(apidsl) > 0 {
dslengine.Execute(apidsl[0], mt)
if apidsl != nil {
dslengine.Execute(apidsl, mt)
}
if mt.Views == nil {
// If the apidsl didn't create any views (or there is no apidsl at all)
Expand All @@ -421,3 +444,23 @@ func CollectionOf(v interface{}, apidsl ...func()) *design.MediaTypeDefinition {
design.GeneratedMediaTypes[canonical] = mt
return mt
}

func parseCollectionOfDSL(paramAndDSL ...interface{}) (string, func()) {
var param string
var dsl func()
var ok bool
if len(paramAndDSL) > 0 {
d := paramAndDSL[len(paramAndDSL)-1]
if dsl, ok = d.(func()); ok {
paramAndDSL = paramAndDSL[:len(paramAndDSL)-1]
}
for _, p := range paramAndDSL {
param, ok = p.(string)
if !ok {
dslengine.ReportError("invalid CollectionOf argument, must be a string or a DSL function", p)
return "", nil
}
}
}
return param, dsl
}
29 changes: 28 additions & 1 deletion design/apidsl/media_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,34 @@ var _ = Describe("CollectionOf", func() {

It("produces a media type", func() {
Ω(col).ShouldNot(BeNil())
Ω(col.Identifier).ShouldNot(BeEmpty())
Ω(col.Identifier).Should(Equal("application/vnd.example; type=collection"))
Ω(col.TypeName).ShouldNot(BeEmpty())
Ω(Design.MediaTypes).Should(HaveKey(col.Identifier))
})
})

Context("defined with a collection identifier", func() {
var col *MediaTypeDefinition
BeforeEach(func() {
dslengine.Reset()
mt := MediaType("application/vnd.example", func() {
Attribute("id")
View("default", func() {
Attribute("id")
})
})
col = CollectionOf(mt, "application/vnd.examples")
Ω(dslengine.Errors).ShouldNot(HaveOccurred())
})

JustBeforeEach(func() {
dslengine.Run()
Ω(dslengine.Errors).ShouldNot(HaveOccurred())
})

It("produces a media type", func() {
Ω(col).ShouldNot(BeNil())
Ω(col.Identifier).Should(Equal("application/vnd.examples"))
Ω(col.TypeName).ShouldNot(BeEmpty())
Ω(Design.MediaTypes).Should(HaveKey(col.Identifier))
})
Expand Down

0 comments on commit b51fe1f

Please sign in to comment.