Reduce Verbosity with Global Examples


#1

Wouldn’t it be great if we had global examples just like global schemas. That way we could make references to examples and schemas entirely generic from resourceTypes.
For example:

schemas:
  - items: |
       { ... }
  - item: |
       { ... }
examples:
   - items: |
       { ... }
   - item: |
       { ... }
resourceTypes: 
- document:
    get:
      responses:
        200:
          description: Returned
          body:
            application/json:
              schema: <<schema>>
              example: <<schema>>
  - collection:
      type: { document: { schema: <<resourcePathName>> } }
      get:
        is: [pageable, orderable]
      post:
        body:
           application/json:
             example: <<resourcePathName | !singularize>>
             schema: <<resourcePathName | !singluarize>>
  - member:
      type: { document: { schema: <<resourcePathName | !singularize>> } }
      put:
        body:
          application/json:
            example: <<resourcePathName | !singularize>>
            schema: <<resourcePathName | !singularize>>
        responses:
          204:
/items:
  type: collection
  /{item}:
    type: member

This will reduce the verbosity of the resource hierarchy and lead to a nice clean definition, where you can almost see the entire API at a glance.


#2

One idea is to allow for another property, peer to example, called examples that would take an array of examples. That in itself does not solve this usecase, but wait…

We’re thinking that there would be top-level (global) patterns called bodies that would contain an array of named patterns, just as resourceTypes and traits do. A body could have a schema and an example or examples.

That might get you all you wanted and then some…


#3

Yes, that could work. The main thing is that we can reference them by name. I guess given their relation to one another, schemas could have sub-sections, like:

schemas:
  - item:
      schema: |
         { ... }
      example: |
         { ... }
 - other:
      schema: ...`

#4

Adding examples to the schema, so that you always have a schemas/example tuple is super helpful and clean.

I’m not sure how much value new value RAML would get from adding an examples root key.


#5

I have a use case where the global examples key would come in handy.

I was talking to people that are writing RAML for some APIs that are largish. And they said that the responses varied depending on the method used, although the schema is the same, the examples are different. Maybe some optional field is returned depending on the method or URI used.

Should RAML consider this case? Or should it be discarded as badly defined API?


#6

It´s already considered. I wouldn´t be too quick to judge the quality of the API. The way to do it is to have global schemas like so

 - get-items: ...
 - post-items: ...

 ....
     schema: get-<<resourcePathName>>
 ...
     schema: post-<<resourcePathName>>

#7

Yes, but what if the schema is the same, but the example is different


#8

Ah, yes, I see what you mean. In that case, rather than have examples as part of the schema defintion, we put examples as siblings to global schemas which is how our original idea began.


#9

Having achieved a complete round trip then… :wink: Can you comment on the proposal above, of having a root-level bodies property, that holds arrays of named body tuples, each consisting of a schema and example or examples?


#10

Even nicer than global examples and schemas because it can reduce the verbosity yet another fraction.
Let´s see how that would be:

bodies:
  - books:
      application/json:
        schema: x
        example: |
          { ... }
/books:
  get:
    responses:
      200:
        body: books

#11

Exactly. Everything you could want in a body. (Very appropriate as I sit here in Las Vegas.)


#12

Hi,

Isn´t the bodies section a symptom of something bigger? When I was trying to describe HTTP endpoints, after bumping into that same problem I started to think that there is some noise in http elements. Urls, for example, have some elements that are not resources. Our human resources integration endpoint has 3 urls for the employee entity: /employee/{id} to get a employee using its system identification, /employee/login/{login} to get it from its login and /employee/cpf/{cpf} to get it from our national identifier. All of them are, in fact, the same resource. Wouldn´t be better to think about operations on entities instead of httpd methods and urls directly?

Something like that:


resource
    employee:
        schema:
        ...
        operation:
            description:Reads employee by its id
            type: read
            url: /employee/{id}
            method: get
            ...
        operation:
            description:Reads employee by its login
            type: read
            url: /employee/login/{login}
            method: get
            ...
        operation:
            description:Reads employee by its cpf
            type: read
            url: /employee/cpf/{cpf}
            method: get
            ...
        operation:
            description:Creates a new employee
            type: create
            url: /employee 
            method: post
        ...

#13

It’s very true that you could have multiple resource paths refer to the same conceptual entity. But in that case, you could choose one to describe your entity in detail, tag it with a YAML anchor, and then have all the others reference this anchor. For example:

/employee/{id}: &employee
  get:
  put:
  patch:
  delete:
/employee/login/{login}: *employee
/employee/cpf/{cpf}: *employee

You could also use a common !include for all of these.

For creating a new employee, I would expect you’d want to post to an /employees collection resource rather than to an /employee resource that would be the same entity as a single employee.