Skip to content

Commit 7d871ae

Browse files
wojciechkaLeFnord
authored andcommitted
Fix mounting APIs in route_param namespaces (#634)
* Fix mounting APIs in route_param namespaces * Added missing tests, based on code from #543 by @milgner Applied on top of latest master * Added changelog * Fix CHANGELOG.md * Cleanup rubocop offences related to this change * Fix rubocop version * Re-added * Your contribution here to CHANGELOG.md
1 parent e9d9447 commit 7d871ae

File tree

5 files changed

+73
-5
lines changed

5 files changed

+73
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#### Fixes
88

9+
* [#267](https://github.com/ruby-grape/grape-swagger/pull/634): Fix mounting APIs in route_param namespaces - [@milgner](https://github.com/milgner), [@wojciechka](https://github.com/wojciechka).
910
* Your contribution here.
1011

1112
### 0.27.3 (July 11, 2017)

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ group :development, :test do
2525
gem 'rake'
2626
gem 'rdoc'
2727
gem 'rspec', '~> 3.0'
28-
gem 'rubocop', '~> 0.49'
28+
gem 'rubocop', '~> 0.49.1'
2929
end
3030

3131
group :test do

lib/grape-swagger.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,24 @@ def combine_namespaces(app)
9090
end
9191
end
9292

93+
def determine_namespaced_routes(name, parent_route)
94+
if parent_route.nil?
95+
@target_class.combined_routes.values.flatten
96+
else
97+
parent_route.reject do |route|
98+
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
99+
end
100+
end
101+
end
102+
93103
def combine_namespace_routes(namespaces)
94104
# iterate over each single namespace
95105
namespaces.each do |name, _|
96106
# get the parent route for the namespace
97107
parent_route_name = extract_parent_route(name)
98108
parent_route = @target_class.combined_routes[parent_route_name]
99109
# fetch all routes that are within the current namespace
100-
namespace_routes = parent_route.reject do |route|
101-
!route_path_start_with?(route, name) || !route_instance_variable_equals?(route, name)
102-
end
110+
namespace_routes = determine_namespaced_routes(name, parent_route)
103111

104112
# default case when not explicitly specified or nested == true
105113
standalone_namespaces = namespaces.reject do |_, ns|
@@ -122,7 +130,10 @@ def combine_namespace_routes(namespaces)
122130
end
123131

124132
def extract_parent_route(name)
125-
name.match(%r{^/?([^/]*).*$})[1]
133+
route_name = name.match(%r{^/?([^/]*).*$})[1]
134+
return route_name unless route_name.include? ':'
135+
matches = name.match(/\/[a-z]+/)
136+
matches.nil? ? route_name : matches[0].delete('/')
126137
end
127138

128139
def route_instance_variable(route)

lib/grape-swagger/doc_methods/tag_name_description.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class << self
77
def build(paths)
88
paths.values.each_with_object([]) do |path, memo|
99
tags = path.values.first[:tags]
10+
next if tags.nil?
1011

1112
case tags
1213
when String

spec/issues/267_nested_namespaces.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
describe 'nested namespaces' do
6+
let(:app) do
7+
Class.new(Grape::API) do
8+
route_param :root do
9+
resources :apps do
10+
route_param :app_id do
11+
resource :build do
12+
desc 'Builds an application'
13+
post do
14+
{ name: 'Test' }
15+
end
16+
end
17+
end
18+
end
19+
end
20+
21+
add_swagger_documentation version: 'v1'
22+
end
23+
end
24+
25+
describe 'combined_namespace_routes' do
26+
it 'parses root namespace properly' do
27+
expect(app.combined_namespace_routes.keys).to include('apps')
28+
end
29+
end
30+
31+
describe '#extract_parent_route' do
32+
it 'extracts parent for non-namespaced path properly' do
33+
expect(app.send(:extract_parent_route, '/apps/:app_id/build')).to eq('apps')
34+
end
35+
36+
it 'extracts parent for namespaced path properly' do
37+
expect(app.send(:extract_parent_route, '/:root/apps/:app_id/build')).to eq('apps')
38+
end
39+
end
40+
41+
describe 'retrieves swagger-documentation on /swagger_doc' do
42+
let(:route_name) { '{root}/apps/{app_id}/build' }
43+
44+
subject do
45+
get '/swagger_doc.json'
46+
JSON.parse(last_response.body)
47+
end
48+
49+
context 'paths' do
50+
specify do
51+
expect(subject['paths'].keys).to include "/#{route_name}"
52+
end
53+
end
54+
end
55+
end

0 commit comments

Comments
 (0)