1

I am currently working on a Swagger documentation for Ruby on Rails API. The API has lots of enumerators (enums) which are included in various models. The enums are stored as hashes and not arrays in the app/models/concerns directory so that they can be modified without issues later.

State Enum (state.rb)

module State
  extend ActiveSupport::Concern
  included do
    enum state: { state1: 'State 1',
                  state2: 'State 2',
                  state3: 'State 3',
                  state4: 'State 4',
                  state5: 'State 5' }
  end
end

However, when I try to represent this in a component schema in Swagger like this:

components:
  schemas:
    State:
      type: object
      properties:
        enum: { state1: 'State 1',
                state2: 'State 2',
                state3: 'State 3',
                state4: 'State 4',
                state5: 'State 5' }

I get an error:

should not have additional properties

state1: 'State 1'

state2: 'State 2'

state3: 'State 3'

state4: 'State 4'

state5: 'State 5'

I want to represent the enums in hashes and not in arrays. Is there any workaround I can get to make this work?

halfer
  • 19,824
  • 17
  • 99
  • 186
Promise Preston
  • 24,334
  • 12
  • 145
  • 143
  • Does this help? https://swagger.io/docs/specification/data-models/enums/ – Helen Mar 24 '20 at 19:35
  • After reading the documentation provided via your link, I tried this: `enum: - state1: 'State 1', - state2: 'State 2'`, but I get the error **should be object.** – Promise Preston Mar 24 '20 at 19:56
  • 1
    I'm not familiar with swagger but it seems like it's an api documentation so the values in the swagger enum are the values you expect to be passed into your api via the client and then if you want to map that to some other value (i.e., "pass in state1 as parameter to set the value to 'State 1') you'd use the description feature to just say that as text? It's like if I'm ordering a drink at a restaurant, I tell them I want a large drink, they know that means 16 ounces, and if I wish to know I can ask them what size that is; but all I need to know is that I need to tell them 'large' – Simple Lime Mar 24 '20 at 20:12
  • The hashes will help in very well for the enums, so that you have `key:value` pairs as it reflects in the database, unlike putting it in a description. – Promise Preston Mar 24 '20 at 20:18
  • 1
    @SimpleLime is correct in that OpenAPI enums are supposed to define just the actual values that an operation expects / API consumers will send. Are consumers supposed to send `"State 1"` or `"state1"` or `{"state1": "State 1"}` as an object or something else? Remember that OpenAPI defines an _API contract_ and not a DB structure. – Helen Mar 24 '20 at 20:52
  • @Helen, and SimpleLime, thanks for your suggestions. I finally figured it out using a swagger documentation for dictionaries. I have shared my solution as an answer. – Promise Preston Mar 24 '20 at 21:49

1 Answers1

1

I finally figured out a way to get it done. This solution applies to OpenAPI 3 – the latest version of the OpenAPI Specification as the point of answering this question.

Here's how I did it:

Solution 1

components:
  schemas:
    State:
      type: object
      additionalProperties:
        type: string
      example:
        state1: State 1
        state2: State 2
        state3: State 3
        state4: State 4
        state5: State 5

This was passing the entire hash into the response body of a request, and thus it was throwing errors

Solution 2:

Another way is to represent them as arrays, which was not my ideal solution, but it allowed Swagger to select only one item from the array to pass into the response body of a request. I would, however, take note that the enums are hashes and I will have to do a collection_select of hashes for the enums on my client-side.

components:
  schemas:
    State:
      type: string
      description: List of States
      enum:
        - State 1
        - State 2
        - State 3
        - State 4
        - State 5

Lastly, whichever solution you choose you can then reference them in other models like this:

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        first_name:
          type: string
        last_name:
          type: string
        password:
          type: string
          format: password
        state:
          $ref: '#/components/schemas/State'

Here's a link to the Swagger Documentation: Dictionaries, HashMaps and Associative Arrays

That's all.

I hope this helps

Promise Preston
  • 24,334
  • 12
  • 145
  • 143