Is it possible to compose an external resourceType from a second external resourceType


#1

I have the usual collection resource type as an external ResourceType RAML file, but I’d like to have an extended version as a second external ResourceType RAML file too (with some extra features). Obviously the second should extend the first (using the type: key).

However, I’m getting this error from the API-workbench when I try to have the second resource type inherit from the first external resourceType using an include.
“a resource or a resourcetype can inherit from a single resourceType”

Am I to assume it’s not really possible to do what I’m trying to at the moment? The implication from the resourceType composition feature is that it should work.


#2

Hi @AGeoghegan, could you share your RAML? Maybe a smaller version that shows the issue, please :wink:

In general, you should be able to do that. For example:

#%RAML 1.0 
title: Test

resourceTypes: 
  readOnlyCollection:
    get:
      description: Returns a list of <<resourcePathName | !singularize>>.<<resourcePathName | !singularize>>
  collection:
    type: readOnlyCollection
    post:
      description: Adds a new <<resourcePathName | !singularize>>. 

#3

Well for a start I was using this type of include file:

#%RAML 1.0 ResourceType
get:
  responses:
    200:
      body:
        application/json:
          type: <<resourcePathName | !singularize | !uppercamelcase>>[]  # e.g. User[]
      description: returns a collection of <<resourcePathName | !uppercamelcase>>.

This appears to be the root of the issue. It seems like these specific include file types seem to be intrinsically unable to handle external references to other types of include files.
For example a traits declaration for an externally composed trait would cause a syntax issue. It just seems a little deficient for handling regular dependencies when trying to adhere to the DRY principle.
I find the more ordinary “library” type considerably more flexible. But even so, I end up having to pay attention to avoid a potential circular reference.
I guess I should have made it more clear in my initial topic that I was referring to this included file type.


#4

No worries :slight_smile:

The main idea around fragments, vs the previous RAML 0.8, was to give files that can be included some meaning and a base so that they can be validated at design-time as well. Previously, you only knew that there is something wrong with a file is after the inclusion. Certainly, that creates a few problems.

There is also a difference between referencing and inclusion, where the former needs some identifier that you can reference, and the latter is appending any node to another node in YAML. And in that lies the crux of the problem. None of the fragments has identifiers that you can easily reference to in nodes like is or type, or others. You need to either include them into a root node inside an API spec like traits or resourceTypes, give it a name, and use that key name for your reference; or use libraries.

In your case, libraries are most probably the most simple solution since you can use them in any fragment. For example:

readonly.raml

#%RAML 1.0 ResourceType
get:
  responses:
    200:
      body:
        application/json:
          type: <<resourcePathName | !singularize | !uppercamelcase>>[]  # e.g. User[]
      description: returns a collection of <<resourcePathName | !uppercamelcase>>.

lib.raml

#%RAML 1.0 Library

resourceTypes:
  readOnly: !include readonly.raml
  collection: !include collection.raml

collection.raml

#%RAML 1.0 ResourceType

uses:
  lib: lib.raml

type: lib.readOnly
post:

That’s how it is supposed to work in RAML 1.0. We are actually trying to figure out what the best way is to add identifiers for files as well and directly reference to them so that you don’t need a library in between. It’s on our list for another version :wink:


#5

As you suggested I resolved the issue using a Library fragment. The library fragments seem much more flexible in some regards.