grape-swagger 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: