grape-swagger

repository·master·Indexed 22 days ago

https://github.com/ruby-grape/grape-swagger

A Ruby gem that provides autogenerated, Swagger-compliant (OpenAPI 2.0) documentation for Grape APIs. It allows developers to expose API structures to tools like Swagger UI via the `add_swagger_documentation` method. The library supports custom model parsers and provides optional integration with Grape::Entity and representable through separate gems.

Tokens
9.8K
Snippets
41
Records
44
Agent score
76%

What's inside grape-swagger

  1. Implement Inheritance with allOf and discriminator

    master

    You can model inheritance in Swagger by using the is_discriminator: true option on a field in the base entity. This will generate allOf definitions in the resulting Swagger JSON, allowing child entities to inherit properties from the parent.

    module Entities
      class Pet < Grape::Entity
        expose :type, documentation: {
          type: 'string',
          is_discriminator: true,
          required: true
        }
        expose :name, documentation: { type: 'string', required: true }
      end
    
      class Cat < Pet
        expose :huntingSkill, documentation: {
          type: 'string',
          description: 'The measured skill for hunting',
          default: 'lazy',
          values: %w[clueless lazy adventurous aggressive]
        }
      end
    end
  2. Update parameter name generation (>= 1.5.0)

    master

    Starting from version 1.5.0, the names generated for body parameter definitions and their references include the HTTP action and path parameters.

    Example: A PUT /things/:id endpoint that previously generated a reference like #/definitions/putThings will now generate #/definitions/putThingsId.

    If you use the nickname option on an endpoint, that nickname will be used for both the parameter name and the definition reference.

    # If endpoint is nicknamed 'put-thing'
    # The generated Swaggerfile will contain:
    { "name": "put-thing", ..., "schema": { "$ref": "#/definitions/put-thing" } }
  3. Use array_use_braces for Array parameter submission

    master

    When defining parameters as an Array type in Grape, you must set array_use_braces: true in add_swagger_documentation. This ensures that elements are submitted using the name[] syntax required for proper array handling.

    # Configuration
    add_swagger_documentation array_use_braces: true
    
    # Parameter definition
    params do
      optional :metadata, type: Array[String]
    end
    
    # Resulting submission format:
    # metadata[]: { "name": "Asset ID", "value": "12345" }
  4. Upgrade to grape-swagger >= 2.2.0

    master

    When upgrading to version 2.2.0 or higher, note the following breaking changes and requirements:

    • Grape Version: The minimum required Grape version is now 2.1. Note that Grape 1.8.0 and 2.0.0 are incompatible with Ruby 3.3+.
    • Namespacing: SwaggerRouting and SwaggerDocumentationAdder are now namespaced under GrapeSwagger::. While top-level aliases exist for backward compatibility, they are deprecated and will be removed in version 3.0. Use GrapeSwagger::SwaggerRouting and GrapeSwagger::SwaggerDocumentationAdder instead.
    • String Type Names: Grape 3.2+ rejects string type names in params blocks. If you use string types for documentation hints, move them under the documentation: key.
    • Custom Type Classes: For Grape 3.2+, custom classes used via type: MyClass must implement MyClass.parse(value) with an arity of 1.
    • Multi-type Params: For Grape 3.2+, type: [A, B] will now output the first declared type in the Swagger documentation.
    # Move string types to documentation key for Grape 3.2+
    optional :foo, documentation: { type: 'Object' }
    
    # Implement parse for custom types on Grape 3.2+
    class MyType
      def self.parse(value) = new(value)
    end
  5. Handle array parameter documentation changes

    master

    In recent versions, grape-swagger documents array parameters within an object schema to align with Grape's JSON structure. Ensure your code uses one of the following two patterns to avoid ambiguous documentation:

    1. Array of primitive types: Use type: Array[Type].
    2. Array of objects: Use a block with type: Array and define requirements inside the block.
    # Array of primitives
    params do
      requires :foo, type: Array[String]
    end
    
    # Array of objects
    params do
      requires :put_params, type: Array do
        requires :op, type: String
        requires :path, type: String
        requires :value, type: String
      end
    end
  6. Configure Model Parsers for Grape::Entity or Representable

    master

    Since version 0.21.0, support for Grape::Entity and representable is provided via separate gems. You must add them to your Gemfile manually.

    If you are not using Rails, you must explicitly load the parser in your application initialization (e.g., require 'grape-swagger/entity').

    # For Grape::Entity
    gem 'grape-swagger-entity', '~> 0.3'
    
    # For representable
    gem 'grape-swagger-representable', '~> 0.2'
  7. Migrate 'notes' to 'detail' block (>= 0.10.2)

    master

    Support for the notes: option in desc has been replaced by a detail option passed via a block. Update your route descriptions to ensure future compatibility.

    # Old way
    desc 'Get all kittens!', notes: 'this will expose all the kittens'
    
    # New way
    desc 'Get all kittens!' do
      detail 'this will expose all the kittens'
    end
  8. Use Grape::Entity for Swagger documentation

    master

    You can use grape-entity and grape-swagger-entity to automatically generate Swagger definitions for your models.

    When using expose, you can pass a documentation: hash to define field-level metadata like type, desc, required, is_array, values, and default.

    To use an entity in an endpoint description, pass it to the entity: option in desc or to the params: option for request body documentation.

    module API
      module Entities
        class Status < Grape::Entity
          expose :text, documentation: { type: 'string', desc: 'Status update text.', required: true }
          expose :links, using: Link, documentation: { type: 'link', is_array: true }
          expose :numbers, documentation: { type: 'integer', desc: 'favourite number', values: [1,2,3,4] }
        end
    
        class Link < Grape::Entity
          expose :href, documentation: { type: 'url' }
          expose :rel, documentation: { type: 'string'}
    
          def self.entity_name
            'LinkedStatus'
          end
        end
      end
    
      class Statuses < Grape::API
        version 'v1'
    
        desc 'Statuses index',
          entity: API::Entities::Status
        get '/statuses' do
          # ...
        end
    
        desc 'Creates a new status',
          entity: API::Entities::Status,
          params: API::Entities::Status.documentation
        post '/statuses' do
            # ...
        end
      end
    end
  9. Secure the Swagger UI

    master

    The Swagger UI can be secured using middleware. When calling add_swagger_documentation, you can configure security using:

    • endpoint_auth_wrapper: The middleware used for securing the UI (e.g., WineBouncer::OAuth2).
    • swagger_endpoint_guard: A guard method and scope (e.g., 'oauth2 false'). Setting a scope like 'oauth2 false' protects the endpoint with OAuth but allows the UI to be visible to everyone. Using a specific scope like 'oauth2 admin' will hide the UI from unauthorized users.
    • token_owner: The method that returns the owner of the token.

    You can also protect specific endpoints using the oauth2 DSL method or hide them entirely using the hidden key in desc with a lambda that checks the token_owner.

    add_swagger_documentation base_path: '/',
                  title: 'My API',
                  doc_version: '0.0.1',
                  hide_documentation_path: true,
                  endpoint_auth_wrapper: WineBouncer::OAuth2,
                  swagger_endpoint_guard: 'oauth2 false',
                  token_owner: 'resource_owner'
    
    # Protecting specific endpoints
    resource :users do
      oauth2 'admin'
      post do
        User.create!...
      end
    end
    
    # Hiding endpoints from unauthorized users
    not_admins = lambda { |token_owner = nil| token_owner.nil? || !token_owner.admin? }
    
    resource :users do
      desc 'Create user', hidden: not_admins
      oauth2 'admin'
      post do
        User.create!...
      end
    end
  10. Document Entity relationships (1xN and 1x1)

    master

    When exposing related entities, you can specify the relationship type in the documentation: hash.

    • 1xN (One-to-Many): Use is_array: true in the documentation hash.
    • 1x1 (One-to-One): is_array is false by default.

    When specifying the type for a relationship, use the full class name, omitting any modules named Entities or Entity (e.g., use Entities::Address or just the class path as required by the parser).

    class Client < Grape::Entity
      expose :name, documentation: { type: 'string', desc: 'Name' }
      # 1xN Example
      expose :addresses, using: Entities::Address,
        documentation: { type: 'Entities::Address', desc: 'Addresses.', param_type: 'body', is_array: true }
    end
  11. How to use grape-swagger

    master

    To generate documentation, mount all your individual Grape APIs onto a single root Grape::API class. In that root class, call add_swagger_documentation. By default, this registers the documentation at the /swagger_doc endpoint.

    Once running, you can view your documentation using Swagger UI or by pointing the online swagger demo to your local documentation URL (e.g., http://localhost:3000/swagger_doc).

    require 'grape-swagger'
    
    module API
      class Root < Grape::API
        format :json
        mount API::Cats
        mount API::Dogs
        mount API::Pirates
        add_swagger_documentation
      end
    end