grape-swagger 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ rvm:
2
+ - 1.9.3
@@ -0,0 +1,46 @@
1
+ ### Next Release
2
+
3
+ ### 0.6.0 (June 19, 2013)
4
+
5
+ * Added Rails 4 support - [@jrhe](https://github.com/jrhe).
6
+ * Fix: document APIs at root level - [@dblock](https://github.com/dblock).
7
+ * Added support for procs in basepath - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
8
+ * Support both `:desc` and `:description` when describing parameters - [@dblock](https://github.com/dblock).
9
+ * Fix: allow parameters such as `name[]` - [@dblock](https://github.com/dblock).
10
+
11
+ ### 0.5.0 (March 28, 2013)
12
+
13
+ * Added Grape 0.5.0 support - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
14
+
15
+ ### 0.4.0 (March 28, 2013)
16
+
17
+ * Support https - [@cutalion](https://github.com/cutalion).
18
+
19
+ ### 0.3.0 (October 19, 2012)
20
+
21
+ * Added version support - [@agileanimal](https://github.com/agileanimal), [@fknappe](https://github.com/fknappe).
22
+ * Added support for nested parameters - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
23
+ * Added basic support for specifying parameters that need to be passed in the header - [@agileanimal](https://github.com/agileanimal).
24
+ * Add possibility to hide the documentation paths in the generated swagger documentation - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
25
+
26
+ ### 0.2.1 (August 17, 2012)
27
+
28
+ * Added support for markdown in notes field - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
29
+ * Fix: compatibility with Rails - [@qwert666](https://github.com/qwert666).
30
+ * Fix: swagger UI history - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
31
+
32
+ ### 0.2.0 (July 27, 2012)
33
+
34
+ * Use resource as root for swagger - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
35
+ * Added support for file uploads, and proper `paramType` - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
36
+ * Added tests - [@nathanvda](https://github.com/nathanvda).
37
+
38
+ ### 0.1.0 (July 19, 2012)
39
+
40
+ * Added some configurability to the generated documentation - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
41
+ * Adapted to rails plugin structure - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
42
+ * Allowed cross origin, so swagger can be used from official site - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
43
+
44
+ ### 0.0.0 (July 19, 2012)
45
+
46
+ * Initial public release - [@tim-vandecasteele](https://github.com/tim-vandecasteele).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "grape-swagger"
8
- s.version = "0.5.0"
8
+ s.version = "0.6.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tim Vandecasteele"]
12
- s.date = "2013-03-28"
12
+ s.date = "2013-06-19"
13
13
  s.description = "A simple way to add proper auto generated documentation - that can be displayed with swagger - to your inline described grape API"
14
14
  s.email = "tim.vandecasteele@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -19,6 +19,8 @@ Gem::Specification.new do |s|
19
19
  s.files = [
20
20
  ".document",
21
21
  ".rvmrc",
22
+ ".travis.yml",
23
+ "CHANGELOG.markdown",
22
24
  "Gemfile",
23
25
  "Gemfile.lock",
24
26
  "LICENSE.txt",
@@ -27,6 +29,7 @@ Gem::Specification.new do |s|
27
29
  "VERSION",
28
30
  "grape-swagger.gemspec",
29
31
  "lib/grape-swagger.rb",
32
+ "spec/default_api_spec.rb",
30
33
  "spec/grape-swagger-helper_spec.rb",
31
34
  "spec/grape-swagger_spec.rb",
32
35
  "spec/non_default_api_spec.rb",
data/lib/grape-swagger.rb CHANGED
@@ -5,24 +5,21 @@ module Grape
5
5
  class << self
6
6
  attr_reader :combined_routes
7
7
 
8
- alias original_mount mount
9
-
10
- def mount(mounts)
11
- original_mount mounts
12
- @combined_routes ||= {}
13
- mounts::routes.each do |route|
14
- resource = route.route_path.match('\/(\w*?)[\.\/\(]').captures.first
15
- next if resource.empty?
16
- @combined_routes[resource.downcase] ||= []
17
- @combined_routes[resource.downcase] << route
18
- end
19
- end
20
-
21
8
  def add_swagger_documentation(options={})
22
9
  documentation_class = create_documentation_class
23
10
 
24
11
  documentation_class.setup({:target_class => self}.merge(options))
25
12
  mount(documentation_class)
13
+
14
+ @combined_routes = {}
15
+ routes.each do |route|
16
+ resource = route.route_path.match('\/(\w*?)[\.\/\(]').captures.first
17
+ next if resource.empty?
18
+ resource.downcase!
19
+ @combined_routes[resource] ||= []
20
+ @combined_routes[resource] << route
21
+ end
22
+
26
23
  end
27
24
 
28
25
  private
@@ -43,7 +40,8 @@ module Grape
43
40
  :base_path => nil,
44
41
  :api_version => '0.1',
45
42
  :markdown => false,
46
- :hide_documentation_path => false
43
+ :hide_documentation_path => false,
44
+ :hide_format => false
47
45
  }
48
46
  options = defaults.merge(options)
49
47
 
@@ -52,6 +50,7 @@ module Grape
52
50
  @@class_name = options[:class_name] || options[:mount_path].gsub('/','')
53
51
  @@markdown = options[:markdown]
54
52
  @@hide_documentation_path = options[:hide_documentation_path]
53
+ @@hide_format = options[:hide_format]
55
54
  api_version = options[:api_version]
56
55
  base_path = options[:base_path]
57
56
 
@@ -66,12 +65,12 @@ module Grape
66
65
  end
67
66
 
68
67
  routes_array = routes.keys.map do |local_route|
69
- { :path => "#{parse_path(route.route_path.gsub('(.:format)', ''),route.route_version)}/#{local_route}.{format}" }
68
+ { :path => "#{parse_path(route.route_path.gsub('(.:format)', ''),route.route_version)}/#{local_route}#{@@hide_format ? '' : '.{format}'}" }
70
69
  end
71
70
  {
72
71
  apiVersion: api_version,
73
72
  swaggerVersion: "1.1",
74
- basePath: base_path || request.base_url,
73
+ basePath: parse_base_path(base_path, request),
75
74
  operations:[],
76
75
  apis: routes_array
77
76
  }
@@ -86,7 +85,7 @@ module Grape
86
85
  header['Access-Control-Request-Method'] = '*'
87
86
  routes = @@target_class::combined_routes[params[:name]]
88
87
  routes_array = routes.map do |route|
89
- notes = route.route_notes && @@markdown ? Kramdown::Document.new(route.route_notes.strip_heredoc).to_html : route.route_notes
88
+ notes = route.route_notes && @@markdown ? Kramdown::Document.new(strip_heredoc(route.route_notes)).to_html : route.route_notes
90
89
  http_codes = parse_http_codes route.route_http_codes
91
90
  operations = {
92
91
  :notes => notes,
@@ -106,7 +105,7 @@ module Grape
106
105
  {
107
106
  apiVersion: api_version,
108
107
  swaggerVersion: "1.1",
109
- basePath: base_path || request.base_url,
108
+ basePath: parse_base_path(base_path, request),
110
109
  resourcePath: "",
111
110
  apis: routes_array
112
111
  }
@@ -121,9 +120,9 @@ module Grape
121
120
  value[:type] = 'file' if value.is_a?(Hash) && value[:type] == 'Rack::Multipart::UploadedFile'
122
121
 
123
122
  dataType = value.is_a?(Hash) ? value[:type]||'String' : 'String'
124
- description = value.is_a?(Hash) ? value[:desc] : ''
123
+ description = value.is_a?(Hash) ? value[:desc] || value[:description] : ''
125
124
  required = value.is_a?(Hash) ? !!value[:required] : false
126
- paramType = path.match(":#{param}") ? 'path' : (method == 'POST') ? 'body' : 'query'
125
+ paramType = path.include?(":#{param}") ? 'path' : (method == 'POST') ? 'form' : 'query'
127
126
  name = (value.is_a?(Hash) && value[:full_name]) || param
128
127
  {
129
128
  paramType: paramType,
@@ -161,7 +160,7 @@ module Grape
161
160
 
162
161
  def parse_path(path, version)
163
162
  # adapt format to swagger format
164
- parsed_path = path.gsub('(.:format)', '.{format}')
163
+ parsed_path = path.gsub '(.:format)', ( @@hide_format ? '' : '.{format}')
165
164
  # This is attempting to emulate the behavior of
166
165
  # Rack::Mount::Strexp. We cannot use Strexp directly because
167
166
  # all it does is generate regular expressions for parsing URLs.
@@ -169,43 +168,35 @@ module Grape
169
168
  # parsed path.
170
169
  parsed_path = parsed_path.gsub(/:([a-zA-Z_]\w*)/, '{\1}')
171
170
  # add the version
172
- parsed_path = parsed_path.gsub('{version}', version) if version
173
- parsed_path
171
+ version ? parsed_path.gsub('{version}', version) : parsed_path
174
172
  end
173
+
175
174
  def parse_http_codes codes
176
175
  codes ||= {}
177
176
  codes.collect do |k, v|
178
177
  {:code => k, :reason => v}
179
178
  end
180
179
  end
180
+
181
+ def try(*a, &b)
182
+ if a.empty? && block_given?
183
+ yield self
184
+ else
185
+ public_send(*a, &b) if respond_to?(a.first)
186
+ end
187
+ end
188
+
189
+ def strip_heredoc(string)
190
+ indent = string.scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
191
+ string.gsub(/^[ \t]{#{indent}}/, '')
192
+ end
193
+
194
+ def parse_base_path(base_path, request)
195
+ (base_path.is_a?(Proc) ? base_path.call(request) : base_path) || request.base_url
196
+ end
181
197
  end
182
198
  end
183
199
  end
184
200
  end
185
201
  end
186
202
  end
187
-
188
- class Object
189
- ##
190
- # @person ? @person.name : nil
191
- # vs
192
- # @person.try(:name)
193
- #
194
- # File activesupport/lib/active_support/core_ext/object/try.rb#L32
195
- def try(*a, &b)
196
- if a.empty? && block_given?
197
- yield self
198
- else
199
- __send__(*a, &b)
200
- end
201
- end
202
- end
203
-
204
- class String
205
- # strip_heredoc from rails
206
- # File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
207
- def strip_heredoc
208
- indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
209
- gsub(/^[ \t]{#{indent}}/, '')
210
- end
211
- end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Default API" do
4
+
5
+ before(:all) do
6
+ class NotAMountedApi < Grape::API
7
+ desc 'this gets something'
8
+ get '/something' do
9
+ {:bla => 'something'}
10
+ end
11
+ add_swagger_documentation
12
+ end
13
+ end
14
+
15
+ def app; NotAMountedApi; end
16
+
17
+ it "should document something" do
18
+ get '/swagger_doc'
19
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/something.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
20
+ end
21
+
22
+ end
@@ -30,7 +30,7 @@ describe "helpers" do
30
30
  ]
31
31
  end
32
32
 
33
- it "should parse params as body for a POST" do
33
+ it "should parse params as form for a POST" do
34
34
  params = {
35
35
  name: {type: 'String', :desc =>"A name", required: true },
36
36
  level: 'max'
@@ -39,8 +39,8 @@ describe "helpers" do
39
39
  method = "POST"
40
40
  @api.parse_params(params, path, method).should ==
41
41
  [
42
- {paramType: "body", name: :name, description:"A name", dataType: "String", required: true},
43
- {paramType: "body", name: :level, description:"", dataType: "String", required: false}
42
+ {paramType: "form", name: :name, description:"A name", dataType: "String", required: true},
43
+ {paramType: "form", name: :level, description:"", dataType: "String", required: false}
44
44
  ]
45
45
  end
46
46
  end
@@ -31,6 +31,34 @@ describe "options: " do
31
31
  end
32
32
  end
33
33
 
34
+ context "overruling the basepath with a proc" do
35
+ before(:all) do
36
+ class ProcBasePathMountedApi < Grape::API
37
+ desc 'this gets something'
38
+ get '/something' do
39
+ {:bla => 'something'}
40
+ end
41
+ end
42
+
43
+ class SimpleApiWithProcBasePath < Grape::API
44
+ mount ProcBasePathMountedApi
45
+ add_swagger_documentation :base_path => lambda { |request| "#{request.base_url}/some_value" }
46
+ end
47
+ end
48
+
49
+ def app; SimpleApiWithProcBasePath end
50
+
51
+ it "retrieves the given base-path on /swagger_doc" do
52
+ get '/swagger_doc'
53
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org/some_value\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/something.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
54
+ end
55
+
56
+ it "retrieves the same given base-path for mounted-api" do
57
+ get '/swagger_doc/something'
58
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org/some_value\", :resourcePath=>\"\", :apis=>[{:path=>\"/something.{format}\", :operations=>[{:notes=>nil, :summary=>\"this gets something\", :nickname=>\"GET-something---format-\", :httpMethod=>\"GET\", :parameters=>[]}]}]}"
59
+ end
60
+ end
61
+
34
62
  context "overruling the version" do
35
63
  before(:all) do
36
64
  class ApiVersionMountedApi < Grape::API
@@ -229,4 +257,27 @@ describe "options: " do
229
257
  last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"https://example.org:80\", :resourcePath=>\"\", :apis=>[{:path=>\"/something.{format}\", :operations=>[{:notes=>nil, :summary=>\"this gets something\", :nickname=>\"GET-something---format-\", :httpMethod=>\"GET\", :parameters=>[]}]}]}"
230
258
  end
231
259
  end
260
+
261
+ context ":hide_format" do
262
+ before(:all) do
263
+ class HidePathsApi < Grape::API
264
+ desc 'this gets something'
265
+ get '/something' do
266
+ {:bla => 'something'}
267
+ end
268
+ end
269
+
270
+ class SimpleApiWithHiddenPaths < Grape::API
271
+ mount ProtectedApi
272
+ add_swagger_documentation :hide_format => true
273
+ end
274
+ end
275
+
276
+ def app; SimpleApiWithHiddenPaths; end
277
+
278
+ it "has no formats" do
279
+ get '/swagger_doc/something'
280
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :resourcePath=>\"\", :apis=>[{:path=>\"/something\", :operations=>[{:notes=>nil, :summary=>\"this gets something\", :nickname=>\"GET-something---format-\", :httpMethod=>\"GET\", :parameters=>[]}]}]}"
281
+ end
282
+ end
232
283
  end
@@ -20,14 +20,23 @@ describe "a simple mounted api" do
20
20
  "XAuthToken" => {description: "A required header.", required: true},
21
21
  "XOtherHeader" => {description: "An optional header.", required: false}
22
22
  },
23
- :http_codes => {
24
- 403 => "invalid pony",
25
- 405 => "no ponies left!"
26
- }
23
+ :http_codes => {
24
+ 403 => "invalid pony",
25
+ 405 => "no ponies left!"
26
+ }
27
27
  }
28
28
  get '/simple_with_headers' do
29
29
  {:bla => 'something_else'}
30
30
  end
31
+
32
+ desc 'this takes an array of parameters', {
33
+ :params => {
34
+ "items[]" => { :description => "array of items" }
35
+ }
36
+ }
37
+ post '/items' do
38
+ {}
39
+ end
31
40
  end
32
41
 
33
42
  class SimpleApi < Grape::API
@@ -40,7 +49,7 @@ describe "a simple mounted api" do
40
49
 
41
50
  it "retrieves swagger-documentation on /swagger_doc" do
42
51
  get '/swagger_doc'
43
- last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/simple.{format}\"}, {:path=>\"/swagger_doc/simple_with_headers.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
52
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/simple.{format}\"}, {:path=>\"/swagger_doc/simple_with_headers.{format}\"}, {:path=>\"/swagger_doc/items.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
44
53
  end
45
54
 
46
55
  it "retrieves the documentation for mounted-api" do
@@ -52,4 +61,9 @@ describe "a simple mounted api" do
52
61
  get '/swagger_doc/simple_with_headers'
53
62
  last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :resourcePath=>\"\", :apis=>[{:path=>\"/simple_with_headers.{format}\", :operations=>[{:notes=>nil, :summary=>\"this gets something else\", :nickname=>\"GET-simple_with_headers---format-\", :httpMethod=>\"GET\", :parameters=>[{:paramType=>\"header\", :name=>\"XAuthToken\", :description=>\"A required header.\", :dataType=>\"String\", :required=>true}, {:paramType=>\"header\", :name=>\"XOtherHeader\", :description=>\"An optional header.\", :dataType=>\"String\", :required=>false}], :errorResponses=>[{:code=>403, :reason=>\"invalid pony\"}, {:code=>405, :reason=>\"no ponies left!\"}]}]}]}"
54
63
  end
64
+
65
+ it "retrieves the documentation for mounted-api that supports multiple parameters" do
66
+ get '/swagger_doc/items'
67
+ last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :resourcePath=>\"\", :apis=>[{:path=>\"/items.{format}\", :operations=>[{:notes=>nil, :summary=>\"this takes an array of parameters\", :nickname=>\"POST-items---format-\", :httpMethod=>\"POST\", :parameters=>[{:paramType=>\"form\", :name=>\"items[]\", :description=>\"array of items\", :dataType=>\"String\", :required=>false}]}]}]}"
68
+ end
55
69
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-swagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-28 00:00:00.000000000 Z
12
+ date: 2013-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grape
@@ -166,6 +166,8 @@ extra_rdoc_files:
166
166
  files:
167
167
  - .document
168
168
  - .rvmrc
169
+ - .travis.yml
170
+ - CHANGELOG.markdown
169
171
  - Gemfile
170
172
  - Gemfile.lock
171
173
  - LICENSE.txt
@@ -174,6 +176,7 @@ files:
174
176
  - VERSION
175
177
  - grape-swagger.gemspec
176
178
  - lib/grape-swagger.rb
179
+ - spec/default_api_spec.rb
177
180
  - spec/grape-swagger-helper_spec.rb
178
181
  - spec/grape-swagger_spec.rb
179
182
  - spec/non_default_api_spec.rb
@@ -194,7 +197,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
197
  version: '0'
195
198
  segments:
196
199
  - 0
197
- hash: 470443031386995496
200
+ hash: 4271109151284297924
198
201
  required_rubygems_version: !ruby/object:Gem::Requirement
199
202
  none: false
200
203
  requirements: