Skip to content

Instantly share code, notes, and snippets.

@jagdeepsingh
Last active April 19, 2019 09:47
Show Gist options
  • Save jagdeepsingh/432e6ecee5824ed400f6ee8dde2b7c39 to your computer and use it in GitHub Desktop.
Save jagdeepsingh/432e6ecee5824ed400f6ee8dde2b7c39 to your computer and use it in GitHub Desktop.
Swagger

Contents:

1 Setup

Install gem swagger-blocks.

# Gemfile
gem 'swagger-blocks', '~> 2.0.2'

Run bundle install.

Back to Top

2 Schemas

Below is the schema example for a user input:

# app/controllers/users_controller.rb
class UsersController
  include Swagger::Blocks

  swagger_schema :UserInput do
    property :first_name, type: :string, example: 'Jagdeep'
    property :last_name, type: :string, example: 'Singh'
    property :vip, type: :boolean
    property :email, type: :string, example: '[email protected]'
    property :gender, type: :integer, format: :int32, example: 1
    property :extra, type: :array, example: [{ foo: :bar }]
  end
end

We can reuse a schema while defining another schema. UserResponse schema below is defined with all the properties from UserInput schema and additional properties id and created_at.

swagger_schema :UserResponse do
  allOf do
    schema do
      property :id, type: :string, example: '59a907676120b29364000049'
      property :created_at, type: :integer, format: :int64, example: 1506065823
    end
    schema '$ref' => :UserInput
  end
end

You can also define schemas for error responses:

swagger_schema :ErrorModel do
  property :errors do
    key :type, :object
    key :properties, {
      base: {
        type: :string
      }
    }
  end
end

Back to Top

3 Paths

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  include Swagger::Blocks

  # PUT /users/:id (update user)
  swagger_path '/users/{id}' do
    operation :put do
      security api_key: []     # This will be defined under `swagger_root`

      key :summary, 'Updates a user'
      key :description, 'Updates a user'
      key :tags, %w[user]

      parameter do
        key :name, :id
        key :in, :path
        key :required, true
        key :description, 'ID of user to be updated'
        key :type, :string
      end

      parameter do
        key :name, :user
        key :in, :body
        key :required, true

        schema do
          key :'$ref', :UserInput
        end
      end

      response 200 do
        key :description, 'user'
        schema '$ref' => :UserResponse
      end

      response 422 do
        key :description, 'unprocessable entity'
        schema '$ref' => :ErrorModel
      end
    end
  end
end

Instead of writing multiple key statements, you can define a parameter by passing it a Hash like this:

parameter name: :id,
          in: :path,
          required: true,
          description: 'ID of user to be updated',
          type: :string
          
parameter name: :user,
          in: :body,
          required: true do
  schema do
    key :'$ref', :UserInput
  end
end

If your response contains an empty object i.e. {}, you can define it as:

response 200 do
  schema type: :object
end

Back to Top

4 Docs

# app/controllers/apidocs_controller.rb
class ApidocsController < ApplicationController
  include Swagger::Blocks

  SWAGGERED_CLASSES = [
    UsersController,
    self
  ].freeze

  swagger_root do
    key :swagger, '2.0'

    info version: APP_VERSION,
         title: 'My Application',
         description: 'Description of API end points used by My Application'

    key :host, 'abcd1234.ngrok.io'        # Replace this with the domain your application is running on
    key :basePath, '/api'                 # Base path for all your end points
    key :consumes, ['application/json']
    key :produces, ['application/json']

    security_definition :api_key, type: :apiKey do
      key :name, 'Authorization'
      key :in, :header
    end
  end

  def index
    render json: Swagger::Blocks.build_root_json(SWAGGERED_CLASSES)
  end
end

We have defined security_definition above for the header HTTP_AUTHORIZATION to be passed in the API requests.

Add security api_key: [] to the swagger_path definitions where you expect Authorization header to be set.

# config/routes.rb
resources :apidocs, only: [:index]

You will also need to enable CORS for this route. Else Swagger will not be able to read the JSON from your server.

# app/controllers/apidocs_controller.rb
after_filter :set_access_control_headers

private

def set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
end

To view the UI, follow below steps:

You will see a nice representation of your API end points.

Back to Top

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment