module Openapi::Mongoid::SpecBuilder

Constants

CRUD_ACTIONS

Public Instance Methods

action_specification_exists?(method, path) click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 474
def action_specification_exists?(method, path)
  swagger_nodes = self.send(:_swagger_nodes)
  node_map = swagger_nodes[:path_node_map]

  node_map.has_key?(path) && node_map[path].data.has_key?(method)
end
build_crud_specification(routes) click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 146
def build_crud_specification(routes)
  name        = spec_resource_name
  sym_name    = name.underscore.to_sym
  plural_name = spec_collection_name
  path        = spec_relative_path
  scopes      = try(:scopes_configuration) || []
  actions     = routes.map {|r| r[2]}.uniq
  json_mime   = %w(application/json)

  include_index   = actions.include?('index') &&
                    !spec_except_actions.include?('index')
  include_create  = actions.include?('create') &&
                    !spec_except_actions.include?('create')
  include_show    = actions.include?('show') &&
                    !spec_except_actions.include?('show')
  include_update  = actions.include?('update') &&
                    !spec_except_actions.include?('update')
  include_destroy = actions.include?('destroy') &&
                    !spec_except_actions.include?('destroy')

  include_collection_actions =
    (include_index || include_create)
  include_resource_actions =
    (include_show || include_update || include_destroy)

  support_search = spec_resource_class.methods.include?(:search)

  if include_collection_actions
    swagger_path path do

      if include_index
        operation :get do
          key :tags,        [plural_name]
          key :summary,     "index#{plural_name}"
          key :operationId, "index#{plural_name}"
          key :produces,    json_mime

          parameter do
            key :name,        :page
            key :description, 'Page number'
            key :type,        :integer
            key :format,      :int32
            key :in,          :query
            key :required,    false
          end

          parameter do
            key :name,        :perPage
            key :description, 'Items per page'
            key :type,        :integer
            key :format,      :int32
            key :in,          :query
            key :required,    false
          end

          parameter do
            key :name,     :fields
            key :in,       :query
            key :required, false
            key :description, 'Return exact model fields'
            key :type,        :array
            items do
              key :type, :string
            end
          end

          parameter do
            key :name,        :methods
            key :description, 'Include model methods'
            key :in,          :query
            key :required,    false
            key :type,        :array
            items do
              key :type, :string
            end
          end

          if support_search
            parameter do
              key :name,        :search
              key :description, 'Search query string'
              key :type,        :string
              key :in,          :query
              key :required,    false
            end
          end

          scopes.each do |k, config|
            scope_name = config[:as]
            scope_type = config[:type]

            if scope_type == :default
              scope_type = :string
            end

            parameter do
              key :name,     scope_name
              key :type,     scope_type
              key :in,       :query
              key :required, false

              if scope_type == :integer
                key :format, :int32
              end
            end
          end

          response 200 do
            key :description, 'Success'
            schema type: :array do
              items do
                key :'$ref', name
              end
            end
          end
        end
      end

      if include_create
        operation :post do
          key :tags,        [plural_name]
          key :summary,     "create#{name}"
          key :operationId, "create#{name}"
          key :produces,    json_mime

          parameter do
            key :name,     "body{#{sym_name}}"
            key :in,       :body
            key :required, true
            schema do
              key :'$ref', "#{name}Input"
            end
          end

          parameter do
            key :name,     :fields
            key :in,       :query
            key :required, false
            key :description, 'Return exact model fields'
            key :type,        :array
            items do
              key :type, :string
            end
          end

          parameter do
            key :name,        :methods
            key :description, 'Include model methods'
            key :in,          :query
            key :required,    false
            key :type,        :array
            items do
              key :type, :string
            end
          end

          response 201 do
            key :description, 'Success'
            schema do
              key :'$ref', name
            end
          end

          response 422 do
            key :description, 'Unprocessable entity error'
            schema do
              key :'$ref', name
            end
          end

        end
      end
    end
  end

  if include_resource_actions
    swagger_path "#{path}/{id}" do

      if include_show
        operation :get do
          key :tags,        [plural_name]
          key :summary,     "show#{name}ById"
          key :operationId, "show#{name}ById"
          key :produces,    json_mime

          parameter do
            key :name,     :id
            key :type,     :string
            key :in,       :path
            key :required, true
          end

          parameter do
            key :name,     :fields
            key :in,       :query
            key :required, false
            key :description, 'Return exact model fields'
            key :type,        :array
            items do
              key :type, :string
            end
          end

          parameter do
            key :name,        :methods
            key :description, 'Include model methods'
            key :in,          :query
            key :required,    false
            key :type,        :array
            items do
              key :type, :string
            end
          end

          response 200 do
            key :description, 'Success'
            schema do
              key :'$ref', name
            end
          end
        end
      end

      if include_update
        operation :put do
          key :tags,        [plural_name]
          key :summary,     "update#{name}"
          key :operationId, "update#{name}"
          key :produces,    json_mime

          parameter do
            key :name,     :id
            key :type,     :string
            key :in,       :path
            key :required, true
          end

          parameter do
            key :name,     :fields
            key :in,       :query
            key :required, false
            key :description, 'Return exact model fields'
            key :type,        :array
            items do
              key :type, :string
            end
          end

          parameter do
            key :name,        :methods
            key :description, 'Include model methods'
            key :in,          :query
            key :required,    false
            key :type,        :array
            items do
              key :type, :string
            end
          end

          parameter do
            key :name,     "body{#{sym_name}}"
            key :in,       :body
            key :required, true
            schema do
              key :'$ref', "#{name}Input"
            end
          end

          response 200 do
            key :description, 'Success'
            schema do
              key :'$ref', name
            end
          end

          response 422 do
            key :description, 'Unprocessable entity error'
            schema do
              key :'$ref', name
            end
          end

        end
      end

      if include_destroy
        operation :delete do
          key :tags,        [plural_name]
          key :summary,     "destroy#{name}"
          key :operationId, "destroy#{name}"

          parameter do
            key :name,     :id
            key :type,     :string
            key :in,       :path
            key :required, true
          end

          response 204 do
            key :description, 'Success'
          end
        end
      end
    end
  end
end
build_openapi_definitions() click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 97
def build_openapi_definitions
  collection_name        = spec_collection_name
  resource_class         = spec_resource_class
  resource_name          = spec_resource_name
  resource_property_name = resource_name.underscore.to_sym

  swagger_schema resource_name do
    build_model_schema(resource_class)

    resource_class.relations.each do |key, relation|
      relation_type = relation.relation.to_s

      if relation_type.include? 'Mongoid::Relations::Embedded'
        relation_name =
          relation.name.to_s.singularize.titleize.remove(' ')

        # TODO: This is not accurate, class might be in the same
        #       namespace as related.
        # namespace = resource_class.to_s.split('::')[0...-1].join('::')
        # generated_embedded_resource_class_name = [namespace, relation_name].join('::')

        # TODO: Add error handler in case class is not guessed here.
        embedded_resource_class =
          (relation.class_name || relation_name).constantize

        if relation_type.include? 'Many'
          property relation.name.to_s, type: :array do
            items do
              build_model_schema(embedded_resource_class)
            end
          end

        else
          property relation.name.to_s.singularize, type: :object do
            build_model_schema(embedded_resource_class)
          end

        end
      end
    end
  end

  swagger_schema "#{resource_name}Input" do
    property resource_property_name, type: :object do
      build_model_schema(resource_class, true)
    end
  end
end
build_openapi_paths() click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 88
def build_openapi_paths
  routes = Openapi::RoutesParser.new(self).routes
  build_crud_specification(routes)

  if Rails.env.development?
    warn_on_undocumented_actions(routes)
  end
end
build_openapi_specification(options) click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 56
def build_openapi_specification(options)
  self.spec_except_actions ||=
    []

  self.spec_base_path =
    options[:base_path]

  self.spec_relative_path ||=
    ('/' + to_s.remove(/Controller$/).gsub('::', '/').underscore).
      remove(spec_base_path)

  self.spec_resource_class ||=
    self.try(:crud_resource_class)

  self.spec_resource_class ||=
    self.to_s.
      split('::').
      last.
      sub(/Controller$/, '').
      singularize.
      constantize

  self.spec_resource_name ||=
    self.spec_resource_class.to_s.remove('::')

  self.spec_collection_name ||=
    self.spec_resource_name.pluralize

  build_openapi_definitions
  build_openapi_paths
end
spec_params(options) click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 48
def spec_params(options)
  self.spec_resource_class  = options[:resource_class]
  self.spec_resource_name   = options[:resource_name]
  self.spec_collection_name = options[:collection_name]
  self.spec_relative_path   = options[:relative_path]
  self.spec_except_actions  = options[:except_actions]
end
warn_on_undocumented_actions(routes) click to toggle source
# File lib/openapi/mongoid/spec_builder.rb, line 453
def warn_on_undocumented_actions(routes)
  custom_routes = routes.select {|r| !CRUD_ACTIONS.include?(r[2])}
  no_spec_methods = custom_routes.select do |route|
    method = route[0].to_sym
    path = route[1].remove(spec_base_path)
    path_sym = path.gsub(/:(\w+)/, '{\1}').to_sym

    ! action_specification_exists?(method, path_sym)
  end

  unless no_spec_methods.empty?
    routes = no_spec_methods.map do |r|
      method = r[0].upcase
      path   = r[1]
      "  #{method} #{path}"
    end.join("\n")

    puts "\n#{self} misses specification for:\n#{routes}\n\n"
  end
end