Skip to content

Commit

Permalink
same refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Scholz committed Mar 16, 2016
1 parent db3ef51 commit 3a97ec1
Show file tree
Hide file tree
Showing 21 changed files with 275 additions and 233 deletions.
7 changes: 2 additions & 5 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Metrics/AbcSize:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 353
Max: 300

# Offense count: 6
Metrics/CyclomaticComplexity:
Expand All @@ -32,7 +32,7 @@ Metrics/MethodLength:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 394
Max: 200

# Offense count: 4
Metrics/PerceivedComplexity:
Expand All @@ -51,7 +51,6 @@ Style/Documentation:
# Offense count: 2
Style/DoubleNegation:
Exclude:
- 'lib/grape-swagger/doc_methods.rb'

# Offense count: 3
# Configuration parameters: Exclude.
Expand All @@ -65,12 +64,10 @@ Style/FileName:
# Configuration parameters: NamePrefix, NamePrefixBlacklist.
Style/PredicateName:
Exclude:
- 'lib/grape-swagger/doc_methods.rb'

# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
Style/RegexpLiteral:
Exclude:
- 'lib/grape-swagger.rb'
- 'lib/grape-swagger/doc_methods.rb'
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
n.n.n / 2016-02-14

n.n.n / 2016-03-16
==================

[#354](https://github.com/ruby-grape/grape-swagger/pull/354) some improvements

- fixes setting of `base_path` and `host`;
- adds possibility to configure the setting of `version` and `base_path` in documented path;
- adds `operationId`

[#353](https://github.com/ruby-grape/grape-swagger/pull/353) resolves issue #352

### 0.10.4 (Next)

[#344](https://github.com/ruby-grape/grape-swagger/pull/) Namespace based tag include in Swagger Json
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ end
## Configure
[host](#host)
[base_path](#base_path)
[mount_path](#mount_path)
[add_base_path](#add_base_path)
[add_version](#add_version)
Expand Down Expand Up @@ -337,6 +338,8 @@ desc 'Get all kittens!', {
entity: Entities::Kitten, # or success
http_codes: [[401, 'KittenBitesError', Entities::BadKitten]] # or failure
# also explicit as hash: [{ code: 401, mssage: 'KittenBitesError', model: Entities::BadKitten }]
produces: [ "array", "of", "mime_types" ],
consumes: [ "array", "of", "mime_types" ]
}
get '/kittens' do
```
Expand Down
9 changes: 8 additions & 1 deletion lib/grape-swagger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
require 'grape-swagger/version'
require 'grape-swagger/endpoint'
require 'grape-swagger/errors'
require 'grape-swagger/doc_methods/produces'

# TODO: loading should be simplified by using a better/more clever dependincy structure
require 'grape-swagger/doc_methods/produces_consumes'
require 'grape-swagger/doc_methods/data_type'
require 'grape-swagger/doc_methods/extensions'
require 'grape-swagger/doc_methods/operation_id'
require 'grape-swagger/doc_methods/optional_object'
require 'grape-swagger/doc_methods/path_string'
require 'grape-swagger/doc_methods/tag_name_description'
require 'grape-swagger/doc_methods'

require 'grape-swagger/markdown/kramdown_adapter'
require 'grape-swagger/markdown/redcarpet_adapter'

Expand Down
23 changes: 23 additions & 0 deletions lib/grape-swagger/doc_methods/operation_id.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module GrapeSwagger
module DocMethods
class OperationId
class << self
def build(method, path = nil)
verb = method.to_s.downcase

unless path.nil?
operation = path.split('/').map(&:capitalize).join
operation.gsub!(/\-(\w)/, &:upcase).delete!('-') if operation.include?('-')
operation.gsub!(/\_(\w)/, &:upcase).delete!('_') if operation.include?('_')
if path.include?('{')
operation.gsub!(/\{(\w)/, &:upcase)
operation.delete!('{').delete!('}')
end
end

"#{verb}#{operation}"
end
end
end
end
end
15 changes: 15 additions & 0 deletions lib/grape-swagger/doc_methods/optional_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module GrapeSwagger
module DocMethods
class OptionalObject
class << self
def build(key, options, request = nil)
if options[key]
options[key].is_a?(Proc) ? options[key].call : options[key]
else
request
end
end
end
end
end
end
29 changes: 29 additions & 0 deletions lib/grape-swagger/doc_methods/path_string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module GrapeSwagger
module DocMethods
class PathString
class << self
def build(path, options = {})
# always removing format
path.sub!(/\(\.\w+?\)$/, '')
path.sub!('(.:format)', '')

# ... format path params
path.gsub!(/:(\w+)/, '{\1}')

# set item from path, this could be used for the definitions object
item = path.gsub(%r{/{(.+?)}}, '').split('/').last.singularize.underscore.camelize || 'Item'

if options[:version] && options[:add_version]
path.sub!('{version}', options[:version])
else
path.sub!('/{version}', '')
end

path = "#{GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options)}#{path}" if options[:add_base_path]

[item, path.start_with?('/') ? path : "/#{path}"]
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module GrapeSwagger
module DocMethods
class Produces
class ProducesConsumes
class << self
def call(*args)
return ['application/json'] unless args.flatten.present?
Expand Down
26 changes: 26 additions & 0 deletions lib/grape-swagger/doc_methods/tag_name_description.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module GrapeSwagger
module DocMethods
class TagNameDescription
class << self
def build(options = {})
target_class = options[:target_class]
namespaces = target_class.combined_namespaces
namespace_routes = target_class.combined_namespace_routes

namespace_routes.keys.map do |local_route|
next if namespace_routes[local_route].map(&:route_hidden).all? { |value| value.respond_to?(:call) ? value.call : value }

original_namespace_name = target_class.combined_namespace_identifiers.key?(local_route) ? target_class.combined_namespace_identifiers[local_route] : local_route
description = namespaces[original_namespace_name] && namespaces[original_namespace_name].options[:desc]
description ||= "Operations about #{original_namespace_name.pluralize}"

{
name: local_route,
description: description
}
end.compact
end
end
end
end
end
93 changes: 19 additions & 74 deletions lib/grape-swagger/endpoint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,13 @@ def swagger_object(target_class, request, options)
swagger: '2.0',
produces: content_types_for(target_class),
authorizations: options[:authorizations],
host: optional_objects(:host, options, request.env['HTTP_HOST']),
basePath: optional_objects(:base_path, options, request.env['SCRIPT_NAME']),
tags: tag_name_description(options),
host: GrapeSwagger::DocMethods::OptionalObject.build(:host, options, request.env['HTTP_HOST']),
basePath: GrapeSwagger::DocMethods::OptionalObject.build(:base_path, options, request.env['SCRIPT_NAME']),
tags: GrapeSwagger::DocMethods::TagNameDescription.build(options),
schemes: options[:scheme]
}.delete_if { |_, value| value.blank? }
end

# helper for swagger object
# gets host and base_path
def optional_objects(key, options, request = nil)
if options[key]
options[key].is_a?(Proc) ? options[key].call : options[key]
else
request
end
end

# building info object
def info_object(infos)
{
Expand Down Expand Up @@ -106,7 +96,7 @@ def path_item(routes, options)
routes.each do |route|
next if hidden?(route)

path = path_string(route, options)
@item, path = GrapeSwagger::DocMethods::PathString.build(route.route_path, options)
@entity = route.route_entity || route.route_success

# ... replacing version params through submitted version
Expand All @@ -124,67 +114,41 @@ def path_item(routes, options)
end
end

def path_string(route, options)
path = route.route_path
# always removing format
path.sub!(/\(\.\w+?\)$/, '')
path.sub!('(.:format)', '')
# ... format params
path.gsub!(/:(\w+)/, '{\1}')

# set item from path, this could be used for the definitions object
@item = path.gsub(%r{/{(.+?)}}, '').split('/').last.singularize.underscore.camelize || 'Item'

if options[:version] && options[:add_version]
path.sub!('{version}', options[:version])
else
path.sub!('/{version}', '')
end

path = "#{optional_objects(:base_path, options)}#{path}" if options[:add_base_path]

path.start_with?('/') ? path : "/#{path}"
end

def method_object(route, options, path)
method = {}
method[:description] = description_object(route, options[:markdown])
method[:headers] = route.route_headers if route.route_headers
method[:produces] = produces_object(route, options)
method[:produces] = produces_object(route, options[:produces] || options[:format])
method[:consumes] = consumes_object(route, options[:format])
method[:parameters] = params_object(route)
method[:responses] = response_object(route)
method[:tags] = tag_object(route, options[:version])
method[:operationId] = operation_id_object(route.route_method, path)
method[:operationId] = GrapeSwagger::DocMethods::OperationId.build(route.route_method, path)
method.delete_if { |_, value| value.blank? }
end

def operation_id_object(method, path = nil)
verb = method.to_s.downcase
unless path.nil?
operation = path.split('/').map(&:capitalize).join
operation.gsub!(/\-(\w)/, &:upcase).delete!('-') if operation.include?('-')
operation.gsub!(/\_(\w)/, &:upcase).delete!('_') if operation.include?('_')
if path.include?('{')
operation.gsub!(/\{(\w)/, &:upcase)
operation.delete!('{').delete!('}')
end
end
"#{verb}#{operation}"
end

def description_object(route, markdown)
description = route.route_desc if route.route_desc.present?
description = route.route_detail if route.route_detail.present?
description = markdown.markdown(description).chomp if markdown
description
end

def produces_object(route, options)
mime_types = GrapeSwagger::DocMethods::Produces.call(options[:format])
def consumes_object(route, format)
method = route.route_method.downcase.to_sym
# require 'pry'; binding.pry if [:post, :put].include?(method)
format = route.route_settings[:description][:consumes] if route.route_settings[:description] && route.route_settings[:description][:consumes]
mime_types = GrapeSwagger::DocMethods::ProducesConsumes.call(format) if [:post, :put].include?(method)

mime_types
end

def produces_object(route, format)
mime_types = GrapeSwagger::DocMethods::ProducesConsumes.call(format)

route_mime_types = [:route_formats, :route_content_types, :route_produces].map do |producer|
possible = route.send(producer)
GrapeSwagger::DocMethods::Produces.call(possible) if possible.present?
GrapeSwagger::DocMethods::ProducesConsumes.call(possible) if possible.present?
end.flatten.compact.uniq

route_mime_types.present? ? route_mime_types : mime_types
Expand Down Expand Up @@ -411,25 +375,6 @@ def primitive?(type)
%w(object integer long float double string byte boolean date dateTime).include? type
end

def tag_name_description(options)
target_class = options[:target_class]
namespaces = target_class.combined_namespaces
namespace_routes = target_class.combined_namespace_routes

namespace_routes.keys.map do |local_route|
next if namespace_routes[local_route].map(&:route_hidden).all? { |value| value.respond_to?(:call) ? value.call : value }

original_namespace_name = target_class.combined_namespace_identifiers.key?(local_route) ? target_class.combined_namespace_identifiers[local_route] : local_route
description = namespaces[original_namespace_name] && namespaces[original_namespace_name].options[:desc]
description ||= "Operations about #{original_namespace_name.pluralize}"

{
name: local_route,
description: description
}
end.compact
end

def tag_object(route, version)
Array(route.route_path.split('{')[0].split('/').reject(&:empty?).delete_if { |i| ((i == route.route_prefix.to_s) || (i == version)) }.first)
end
Expand Down
15 changes: 0 additions & 15 deletions spec/lib/endpoint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,4 @@
describe Grape::Endpoint do
subject { described_class.new(Grape::Util::InheritableSetting.new, {path: '/', method: :get}) }

describe 'operation_id_object' do
specify do
expect(subject.operation_id_object('GET')).to eql 'get'
expect(subject.operation_id_object('get')).to eql 'get'
expect(subject.operation_id_object(:get)).to eql 'get'
expect(subject.operation_id_object('GET', 'foo')).to eql 'getFoo'
expect(subject.operation_id_object('GET', '/foo')).to eql 'getFoo'
expect(subject.operation_id_object('GET', 'bar/foo')).to eql 'getBarFoo'
expect(subject.operation_id_object('GET', 'bar/foo{id}')).to eql 'getBarFooId'
expect(subject.operation_id_object('GET', '/bar_foo{id}')).to eql 'getBarFooId'
expect(subject.operation_id_object('GET', '/bar-foo{id}')).to eql 'getBarFooId'
expect(subject.operation_id_object('GET', '/simple_test/bar-foo{id}')).to eql 'getSimpleTestBarFooId'
end
end

end
24 changes: 24 additions & 0 deletions spec/lib/operation_id_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'spec_helper'

describe GrapeSwagger::DocMethods::OperationId do
subject { described_class }

specify { expect(subject).to eql GrapeSwagger::DocMethods::OperationId }
specify { expect(subject).to respond_to :build }

describe 'build' do
specify do
expect(subject.build('GET')).to eql 'get'
expect(subject.build('get')).to eql 'get'
expect(subject.build(:get)).to eql 'get'
expect(subject.build('GET', 'foo')).to eql 'getFoo'
expect(subject.build('GET', '/foo')).to eql 'getFoo'
expect(subject.build('GET', 'bar/foo')).to eql 'getBarFoo'
expect(subject.build('GET', 'bar/foo{id}')).to eql 'getBarFooId'
expect(subject.build('GET', '/bar_foo{id}')).to eql 'getBarFooId'
expect(subject.build('GET', '/bar-foo{id}')).to eql 'getBarFooId'
expect(subject.build('GET', '/simple_test/bar-foo{id}')).to eql 'getSimpleTestBarFooId'
end
end

end
Loading

0 comments on commit 3a97ec1

Please sign in to comment.