class Grape::API

Attributes

combined_namespaces[R]
combined_routes[R]

Public Class Methods

add_swagger_documentation(options = {}) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 7
def add_swagger_documentation(options = {})
  documentation_class = create_documentation_class
  documentation_class.setup({ target_class: self }.merge(options))
  mount(documentation_class)

  @combined_routes = {}
  routes.each do |route|
    route_match = route.route_path.split(route.route_prefix).last.match('\/([\w|-]*?)[\.\/\(]')
    next if route_match.nil?
    resource = route_match.captures.first
    next if resource.empty?
    resource.downcase!
    @combined_routes[resource] ||= []
    next if @@hide_documentation_path && route.route_path.include?(@@mount_path)
    @combined_routes[resource] << route
  end

  @combined_namespaces = {}
  combine_namespaces(self)
end

Private Class Methods

as_markdown(description) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 223
def as_markdown(description)
  description && @@markdown ? Kramdown::Document.new(strip_heredoc(description), input: 'GFM', enable_coderay: false).to_html : description
end
combine_namespaces(app) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 30
def combine_namespaces(app)
  app.endpoints.each do |endpoint|
    ns = if endpoint.respond_to?(:namespace_stackable)
           endpoint.namespace_stackable(:namespace).last
         else
           endpoint.settings.stack.last[:namespace]
         end
    # use the full namespace here (not the latest level only)
    # and strip leading slash
    @combined_namespaces[endpoint.namespace.sub(/^\//, '')] = ns if ns

    combine_namespaces(endpoint.options[:app]) if endpoint.options[:app]
  end
end
content_types_for(target_class) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 292
def content_types_for(target_class)
  content_types = (target_class.settings[:content_types] || {}).values

  if content_types.empty?
    formats       = [target_class.settings[:format], target_class.settings[:default_format]].compact.uniq
    formats       = Grape::Formatter::Base.formatters({}).keys if formats.empty?
    content_types = Grape::ContentTypes::CONTENT_TYPES.select { |content_type, _mime_type| formats.include? content_type }.values
  end

  content_types.uniq
end
create_documentation_class() click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 45
def create_documentation_class
  Class.new(Grape::API) do
    class << self
      def name
        @@class_name
      end
    end

    def self.setup(options)
      defaults = {
        target_class: nil,
        mount_path: '/swagger_doc',
        mount_with_version: false,
        base_path: nil,
        api_version: '0.1',
        markdown: false,
        hide_documentation_path: false,
        hide_format: false,
        format: nil,
        models: [],
        info: {},
        authorizations: nil,
        root_base_path: true,
        api_documentation: { desc: 'Swagger compatible API description' },
        specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
      }

      options = defaults.merge(options)

      target_class     = options[:target_class]
      api_version      = options[:api_version]
      @@mount_path     = options[:mount_path] + ((options[:mount_with_version] and api_version.present?) ? "/#{api_version}" : '')
      @@class_name     = options[:class_name] || options[:mount_path].gsub('/', '')
      @@markdown       = options[:markdown]
      @@hide_format    = options[:hide_format]
      base_path        = options[:base_path]
      authorizations   = options[:authorizations]
      root_base_path   = options[:root_base_path]
      extra_info       = options[:info]
      api_doc          = options[:api_documentation].dup
      specific_api_doc = options[:specific_api_documentation].dup
      @@models         = options[:models] || []
      @@hide_documentation_path = options[:hide_documentation_path]

      if options[:format]
        [:format, :default_format, :default_error_formatter].each do |method|
          send(method, options[:format])
        end
      end

      desc api_doc.delete(:desc), params: api_doc.delete(:params)
      get @@mount_path do
        header['Access-Control-Allow-Origin']   = '*'
        header['Access-Control-Request-Method'] = '*'

        routes = target_class.combined_routes
        namespaces = target_class.combined_namespaces

        if @@hide_documentation_path
          routes.reject! { |route, _value| "/#{route}/".index(parse_path(@@mount_path, nil) << '/') == 0 }
        end

        routes_array = routes.keys.map do |local_route|
          next if routes[local_route].all?(&:route_hidden)

          url_format  = '.{format}' unless @@hide_format

          description = namespaces[local_route] && namespaces[local_route].options[:desc]
          description ||= "Operations about #{local_route.pluralize}"

          {
            path: "/#{local_route}#{url_format}",
            description: description
          }
        end.compact

        output = {
          apiVersion:     api_version,
          swaggerVersion: '1.2',
          produces:       content_types_for(target_class),
          apis:           routes_array,
          info:           parse_info(extra_info)
        }

        output[:authorizations] = authorizations unless authorizations.nil? || authorizations.empty?

        output
      end

      desc specific_api_doc.delete(:desc), params: {
        'name' => {
          desc: 'Resource name of mounted API',
          type: 'string',
          required: true
        }
      }.merge(specific_api_doc.delete(:params) || {})
      get "#{@@mount_path}/:name" do
        header['Access-Control-Allow-Origin']   = '*'
        header['Access-Control-Request-Method'] = '*'

        models = []
        routes = target_class.combined_routes[params[:name]]
        error!('Not Found', 404) unless routes

        ops = routes.reject(&:route_hidden).group_by do |route|
          parse_path(route.route_path, api_version)
        end

        error!('Not Found', 404) unless ops.any?

        apis = []

        ops.each do |path, op_routes|
          operations = op_routes.map do |route|
            notes       = as_markdown(route.route_notes)

            http_codes  = parse_http_codes(route.route_http_codes, models)

            models << @@models if @@models.present?

            models << route.route_entity if route.route_entity.present?

            models = models_with_included_presenters(models.flatten.compact)

            operation = {
              notes: notes.to_s,
              summary: route.route_description || '',
              nickname: route.route_nickname || (route.route_method + route.route_path.gsub(/[\/:\(\)\.]/, '-')),
              method: route.route_method,
              parameters: parse_header_params(route.route_headers) + parse_params(route.route_params, route.route_path, route.route_method),
              type: 'void'
            }
            operation[:authorizations] = route.route_authorizations unless route.route_authorizations.nil? || route.route_authorizations.empty?
            if operation[:parameters].any? { | param | param[:type] == 'File' }
              operation.merge!(consumes: ['multipart/form-data'])
            end
            operation.merge!(responseMessages: http_codes) unless http_codes.empty?

            if route.route_entity
              type = parse_entity_name(route.route_entity)
              if route.instance_variable_get(:@options)[:is_array]
                operation.merge!(
                  'type' => 'array',
                  'items' => generate_typeref(type)
                )
              else
                operation.merge!('type' => type)
              end
            end

            operation[:nickname] = route.route_nickname if route.route_nickname
            operation
          end.compact
          apis << {
            path: path,
            operations: operations
          }
        end

        api_description = {
          apiVersion:     api_version,
          swaggerVersion: '1.2',
          resourcePath:   "/#{params[:name]}",
          produces:       content_types_for(target_class),
          apis:           apis
        }

        base_path                        = parse_base_path(base_path, request)
        api_description[:basePath]       = base_path if base_path && base_path.size > 0 && root_base_path != false
        api_description[:models]         = parse_entity_models(models) unless models.empty?
        api_description[:authorizations] = authorizations if authorizations

        api_description
      end
    end

    helpers do

      def as_markdown(description)
        description && @@markdown ? Kramdown::Document.new(strip_heredoc(description), input: 'GFM', enable_coderay: false).to_html : description
      end

      def parse_params(params, path, method)
        params ||= []
        params.map do |param, value|
          value[:type] = 'File' if value.is_a?(Hash) && value[:type] == 'Rack::Multipart::UploadedFile'
          items = {}

          raw_data_type = value.is_a?(Hash) ? (value[:type] || 'string').to_s : 'string'
          data_type     = case raw_data_type
                          when 'Boolean', 'Date', 'Integer', 'String'
                            raw_data_type.downcase
                          when 'BigDecimal'
                            'long'
                          when 'DateTime'
                            'dateTime'
                          when 'Numeric'
                            'double'
                          else
                            parse_entity_name(raw_data_type)
                          end
          description   = value.is_a?(Hash) ? value[:desc] || value[:description] : ''
          required      = value.is_a?(Hash) ? !!value[:required] : false
          default_value = value.is_a?(Hash) ? value[:default] : nil
          is_array      = value.is_a?(Hash) ? (value[:is_array] || false) : false
          enum_values   = value.is_a?(Hash) ? value[:values] : nil
          enum_values   = enum_values.call if enum_values && enum_values.is_a?(Proc)

          if value.is_a?(Hash) && value.key?(:param_type)
            param_type  = value[:param_type]
            if is_array
              items     = { '$ref' => data_type }
              data_type = 'array'
            end
          else
            param_type  = case
                          when path.include?(":#{param}")
                            'path'
                          when %w(POST PUT PATCH).include?(method)
                            if is_primitive?(data_type)
                              'form'
                            else
                              'body'
                            end
                          else
                            'query'
                          end
          end
          name          = (value.is_a?(Hash) && value[:full_name]) || param

          parsed_params = {
            paramType:     param_type,
            name:          name,
            description:   as_markdown(description),
            type:          data_type,
            required:      required,
            allowMultiple: is_array
          }
          parsed_params.merge!(format: 'int32') if data_type == 'integer'
          parsed_params.merge!(format: 'int64') if data_type == 'long'
          parsed_params.merge!(items: items) if items.present?
          parsed_params.merge!(defaultValue: default_value) if default_value
          parsed_params.merge!(enum: enum_values) if enum_values
          parsed_params
        end
      end

      def content_types_for(target_class)
        content_types = (target_class.settings[:content_types] || {}).values

        if content_types.empty?
          formats       = [target_class.settings[:format], target_class.settings[:default_format]].compact.uniq
          formats       = Grape::Formatter::Base.formatters({}).keys if formats.empty?
          content_types = Grape::ContentTypes::CONTENT_TYPES.select { |content_type, _mime_type| formats.include? content_type }.values
        end

        content_types.uniq
      end

      def parse_info(info)
        {
          contact:            info[:contact],
          description:        as_markdown(info[:description]),
          license:            info[:license],
          licenseUrl:         info[:license_url],
          termsOfServiceUrl:  info[:terms_of_service_url],
          title:              info[:title]
        }.delete_if { |_, value| value.blank? }
      end

      def parse_header_params(params)
        params ||= []

        params.map do |param, value|
          data_type     = 'String'
          description   = value.is_a?(Hash) ? value[:description] : ''
          required      = value.is_a?(Hash) ? !!value[:required] : false
          default_value = value.is_a?(Hash) ? value[:default] : nil
          param_type    = 'header'

          parsed_params = {
            paramType:    param_type,
            name:         param,
            description:  as_markdown(description),
            type:         data_type,
            required:     required
          }

          parsed_params.merge!(defaultValue: default_value) if default_value

          parsed_params
        end
      end

      def parse_path(path, version)
        # adapt format to swagger format
        parsed_path = path.gsub('(.:format)', @@hide_format ? '' : '.{format}')
        # This is attempting to emulate the behavior of
        # Rack::Mount::Strexp. We cannot use Strexp directly because
        # all it does is generate regular expressions for parsing URLs.
        # TODO: Implement a Racc tokenizer to properly generate the
        # parsed path.
        parsed_path = parsed_path.gsub(/:([a-zA-Z_]\w*)/, '{\1}')
        # add the version
        version ? parsed_path.gsub('{version}', version) : parsed_path
      end

      def parse_entity_name(model)
        if model.respond_to?(:entity_name)
          model.entity_name
        else
          name = model.to_s
          entity_parts = name.split('::')
          entity_parts.reject! { |p| p == 'Entity' || p == 'Entities' }
          entity_parts.join('::')
        end
      end

      def parse_entity_models(models)
        result = {}
        models.each do |model|
          name       = parse_entity_name(model)
          properties = {}
          required   = []

          model.documentation.each do |property_name, property_info|
            p = property_info.dup

            required << property_name.to_s if p.delete(:required)

            if p.delete(:is_array)
              p[:items] = generate_typeref(p[:type])
              p[:type] = 'array'
            else
              p.merge! generate_typeref(p.delete(:type))
            end

            # rename Grape Entity's "desc" to "description"
            property_description = p.delete(:desc)
            p[:description] = property_description if property_description

            # rename Grape's 'values' to 'enum'
            select_values = p.delete(:values)
            if select_values
              select_values = select_values.call if select_values.is_a?(Proc)
              p[:enum] = select_values
            end

            properties[property_name] = p

          end

          result[name] = {
            id:         model.instance_variable_get(:@root) || name,
            properties: properties
          }
          result[name].merge!(required: required) unless required.empty?
        end

        result
      end

      def models_with_included_presenters(models)
        all_models = models

        models.each do |model|
          # get model references from exposures with a documentation
          additional_models = model.exposures.map do |_, config|
            config[:using] if config.key?(:documentation)
          end.compact

          all_models += additional_models
        end

        all_models
      end

      def is_primitive?(type)
        %w(integer long float double string byte boolean date dateTime).include? type
      end

      def generate_typeref(type)
        if is_primitive? type
          { 'type' => type }
        else
          { '$ref' => type }
        end
      end

      def parse_http_codes(codes, models)
        codes ||= {}
        codes.map do |k, v, m|
          models << m if m
          http_code_hash = {
            code: k,
            message: v
          }
          http_code_hash[:responseModel] = parse_entity_name(m) if m
          http_code_hash
        end
      end

      def try(*args, &block)
        if args.empty? && block_given?
          yield self
        elsif respond_to?(args.first)
          public_send(*args, &block)
        end
      end

      def strip_heredoc(string)
        indent = string.scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
        string.gsub(/^[ \t]{#{indent}}/, '')
      end

      def parse_base_path(base_path, request)
        if base_path.is_a?(Proc)
          base_path.call(request)
        elsif base_path.is_a?(String)
          URI(base_path).relative? ? URI.join(request.base_url, base_path).to_s : base_path
        else
          request.base_url
        end
      end
    end
  end
end
generate_typeref(type) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 426
def generate_typeref(type)
  if is_primitive? type
    { 'type' => type }
  else
    { '$ref' => type }
  end
end
is_primitive?(type) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 422
def is_primitive?(type)
  %w(integer long float double string byte boolean date dateTime).include? type
end
models_with_included_presenters(models) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 407
def models_with_included_presenters(models)
  all_models = models

  models.each do |model|
    # get model references from exposures with a documentation
    additional_models = model.exposures.map do |_, config|
      config[:using] if config.key?(:documentation)
    end.compact

    all_models += additional_models
  end

  all_models
end
name() click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 48
def name
  @@class_name
end
parse_base_path(base_path, request) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 460
def parse_base_path(base_path, request)
  if base_path.is_a?(Proc)
    base_path.call(request)
  elsif base_path.is_a?(String)
    URI(base_path).relative? ? URI.join(request.base_url, base_path).to_s : base_path
  else
    request.base_url
  end
end
parse_entity_models(models) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 363
def parse_entity_models(models)
  result = {}
  models.each do |model|
    name       = parse_entity_name(model)
    properties = {}
    required   = []

    model.documentation.each do |property_name, property_info|
      p = property_info.dup

      required << property_name.to_s if p.delete(:required)

      if p.delete(:is_array)
        p[:items] = generate_typeref(p[:type])
        p[:type] = 'array'
      else
        p.merge! generate_typeref(p.delete(:type))
      end

      # rename Grape Entity's "desc" to "description"
      property_description = p.delete(:desc)
      p[:description] = property_description if property_description

      # rename Grape's 'values' to 'enum'
      select_values = p.delete(:values)
      if select_values
        select_values = select_values.call if select_values.is_a?(Proc)
        p[:enum] = select_values
      end

      properties[property_name] = p

    end

    result[name] = {
      id:         model.instance_variable_get(:@root) || name,
      properties: properties
    }
    result[name].merge!(required: required) unless required.empty?
  end

  result
end
parse_entity_name(model) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 352
def parse_entity_name(model)
  if model.respond_to?(:entity_name)
    model.entity_name
  else
    name = model.to_s
    entity_parts = name.split('::')
    entity_parts.reject! { |p| p == 'Entity' || p == 'Entities' }
    entity_parts.join('::')
  end
end
parse_header_params(params) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 315
def parse_header_params(params)
  params ||= []

  params.map do |param, value|
    data_type     = 'String'
    description   = value.is_a?(Hash) ? value[:description] : ''
    required      = value.is_a?(Hash) ? !!value[:required] : false
    default_value = value.is_a?(Hash) ? value[:default] : nil
    param_type    = 'header'

    parsed_params = {
      paramType:    param_type,
      name:         param,
      description:  as_markdown(description),
      type:         data_type,
      required:     required
    }

    parsed_params.merge!(defaultValue: default_value) if default_value

    parsed_params
  end
end
parse_http_codes(codes, models) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 434
def parse_http_codes(codes, models)
  codes ||= {}
  codes.map do |k, v, m|
    models << m if m
    http_code_hash = {
      code: k,
      message: v
    }
    http_code_hash[:responseModel] = parse_entity_name(m) if m
    http_code_hash
  end
end
parse_info(info) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 304
def parse_info(info)
  {
    contact:            info[:contact],
    description:        as_markdown(info[:description]),
    license:            info[:license],
    licenseUrl:         info[:license_url],
    termsOfServiceUrl:  info[:terms_of_service_url],
    title:              info[:title]
  }.delete_if { |_, value| value.blank? }
end
parse_params(params, path, method) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 227
def parse_params(params, path, method)
  params ||= []
  params.map do |param, value|
    value[:type] = 'File' if value.is_a?(Hash) && value[:type] == 'Rack::Multipart::UploadedFile'
    items = {}

    raw_data_type = value.is_a?(Hash) ? (value[:type] || 'string').to_s : 'string'
    data_type     = case raw_data_type
                    when 'Boolean', 'Date', 'Integer', 'String'
                      raw_data_type.downcase
                    when 'BigDecimal'
                      'long'
                    when 'DateTime'
                      'dateTime'
                    when 'Numeric'
                      'double'
                    else
                      parse_entity_name(raw_data_type)
                    end
    description   = value.is_a?(Hash) ? value[:desc] || value[:description] : ''
    required      = value.is_a?(Hash) ? !!value[:required] : false
    default_value = value.is_a?(Hash) ? value[:default] : nil
    is_array      = value.is_a?(Hash) ? (value[:is_array] || false) : false
    enum_values   = value.is_a?(Hash) ? value[:values] : nil
    enum_values   = enum_values.call if enum_values && enum_values.is_a?(Proc)

    if value.is_a?(Hash) && value.key?(:param_type)
      param_type  = value[:param_type]
      if is_array
        items     = { '$ref' => data_type }
        data_type = 'array'
      end
    else
      param_type  = case
                    when path.include?(":#{param}")
                      'path'
                    when %w(POST PUT PATCH).include?(method)
                      if is_primitive?(data_type)
                        'form'
                      else
                        'body'
                      end
                    else
                      'query'
                    end
    end
    name          = (value.is_a?(Hash) && value[:full_name]) || param

    parsed_params = {
      paramType:     param_type,
      name:          name,
      description:   as_markdown(description),
      type:          data_type,
      required:      required,
      allowMultiple: is_array
    }
    parsed_params.merge!(format: 'int32') if data_type == 'integer'
    parsed_params.merge!(format: 'int64') if data_type == 'long'
    parsed_params.merge!(items: items) if items.present?
    parsed_params.merge!(defaultValue: default_value) if default_value
    parsed_params.merge!(enum: enum_values) if enum_values
    parsed_params
  end
end
parse_path(path, version) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 339
def parse_path(path, version)
  # adapt format to swagger format
  parsed_path = path.gsub('(.:format)', @@hide_format ? '' : '.{format}')
  # This is attempting to emulate the behavior of
  # Rack::Mount::Strexp. We cannot use Strexp directly because
  # all it does is generate regular expressions for parsing URLs.
  # TODO: Implement a Racc tokenizer to properly generate the
  # parsed path.
  parsed_path = parsed_path.gsub(/:([a-zA-Z_]\w*)/, '{\1}')
  # add the version
  version ? parsed_path.gsub('{version}', version) : parsed_path
end
setup(options) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 53
def self.setup(options)
  defaults = {
    target_class: nil,
    mount_path: '/swagger_doc',
    mount_with_version: false,
    base_path: nil,
    api_version: '0.1',
    markdown: false,
    hide_documentation_path: false,
    hide_format: false,
    format: nil,
    models: [],
    info: {},
    authorizations: nil,
    root_base_path: true,
    api_documentation: { desc: 'Swagger compatible API description' },
    specific_api_documentation: { desc: 'Swagger compatible API description for specific API' }
  }

  options = defaults.merge(options)

  target_class     = options[:target_class]
  api_version      = options[:api_version]
  @@mount_path     = options[:mount_path] + ((options[:mount_with_version] and api_version.present?) ? "/#{api_version}" : '')
  @@class_name     = options[:class_name] || options[:mount_path].gsub('/', '')
  @@markdown       = options[:markdown]
  @@hide_format    = options[:hide_format]
  base_path        = options[:base_path]
  authorizations   = options[:authorizations]
  root_base_path   = options[:root_base_path]
  extra_info       = options[:info]
  api_doc          = options[:api_documentation].dup
  specific_api_doc = options[:specific_api_documentation].dup
  @@models         = options[:models] || []
  @@hide_documentation_path = options[:hide_documentation_path]

  if options[:format]
    [:format, :default_format, :default_error_formatter].each do |method|
      send(method, options[:format])
    end
  end

  desc api_doc.delete(:desc), params: api_doc.delete(:params)
  get @@mount_path do
    header['Access-Control-Allow-Origin']   = '*'
    header['Access-Control-Request-Method'] = '*'

    routes = target_class.combined_routes
    namespaces = target_class.combined_namespaces

    if @@hide_documentation_path
      routes.reject! { |route, _value| "/#{route}/".index(parse_path(@@mount_path, nil) << '/') == 0 }
    end

    routes_array = routes.keys.map do |local_route|
      next if routes[local_route].all?(&:route_hidden)

      url_format  = '.{format}' unless @@hide_format

      description = namespaces[local_route] && namespaces[local_route].options[:desc]
      description ||= "Operations about #{local_route.pluralize}"

      {
        path: "/#{local_route}#{url_format}",
        description: description
      }
    end.compact

    output = {
      apiVersion:     api_version,
      swaggerVersion: '1.2',
      produces:       content_types_for(target_class),
      apis:           routes_array,
      info:           parse_info(extra_info)
    }

    output[:authorizations] = authorizations unless authorizations.nil? || authorizations.empty?

    output
  end

  desc specific_api_doc.delete(:desc), params: {
    'name' => {
      desc: 'Resource name of mounted API',
      type: 'string',
      required: true
    }
  }.merge(specific_api_doc.delete(:params) || {})
  get "#{@@mount_path}/:name" do
    header['Access-Control-Allow-Origin']   = '*'
    header['Access-Control-Request-Method'] = '*'

    models = []
    routes = target_class.combined_routes[params[:name]]
    error!('Not Found', 404) unless routes

    ops = routes.reject(&:route_hidden).group_by do |route|
      parse_path(route.route_path, api_version)
    end

    error!('Not Found', 404) unless ops.any?

    apis = []

    ops.each do |path, op_routes|
      operations = op_routes.map do |route|
        notes       = as_markdown(route.route_notes)

        http_codes  = parse_http_codes(route.route_http_codes, models)

        models << @@models if @@models.present?

        models << route.route_entity if route.route_entity.present?

        models = models_with_included_presenters(models.flatten.compact)

        operation = {
          notes: notes.to_s,
          summary: route.route_description || '',
          nickname: route.route_nickname || (route.route_method + route.route_path.gsub(/[\/:\(\)\.]/, '-')),
          method: route.route_method,
          parameters: parse_header_params(route.route_headers) + parse_params(route.route_params, route.route_path, route.route_method),
          type: 'void'
        }
        operation[:authorizations] = route.route_authorizations unless route.route_authorizations.nil? || route.route_authorizations.empty?
        if operation[:parameters].any? { | param | param[:type] == 'File' }
          operation.merge!(consumes: ['multipart/form-data'])
        end
        operation.merge!(responseMessages: http_codes) unless http_codes.empty?

        if route.route_entity
          type = parse_entity_name(route.route_entity)
          if route.instance_variable_get(:@options)[:is_array]
            operation.merge!(
              'type' => 'array',
              'items' => generate_typeref(type)
            )
          else
            operation.merge!('type' => type)
          end
        end

        operation[:nickname] = route.route_nickname if route.route_nickname
        operation
      end.compact
      apis << {
        path: path,
        operations: operations
      }
    end

    api_description = {
      apiVersion:     api_version,
      swaggerVersion: '1.2',
      resourcePath:   "/#{params[:name]}",
      produces:       content_types_for(target_class),
      apis:           apis
    }

    base_path                        = parse_base_path(base_path, request)
    api_description[:basePath]       = base_path if base_path && base_path.size > 0 && root_base_path != false
    api_description[:models]         = parse_entity_models(models) unless models.empty?
    api_description[:authorizations] = authorizations if authorizations

    api_description
  end
end
strip_heredoc(string) click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 455
def strip_heredoc(string)
  indent = string.scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
  string.gsub(/^[ \t]{#{indent}}/, '')
end
try(*args) { |self| ... } click to toggle source
# File lib/swagger/grape_swagger_modified.rb, line 447
def try(*args, &block)
  if args.empty? && block_given?
    yield self
  elsif respond_to?(args.first)
    public_send(*args, &block)
  end
end