swagger-docs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f911cef6a9a1c31b6a3eb7b20a9475708d84b450
4
+ data.tar.gz: 7c7561937304375ceacc3738e4fcd68c4b3cc228
5
+ SHA512:
6
+ metadata.gz: 862ec9249db73769611ae420128215e7ac356911cf42983560eb22083f9a8dc11ff9c46c4bbb20daecc09afe613b930dddf18c0bdd0e741b8a4edb21c229c14d
7
+ data.tar.gz: 878c2194761ad4d6ce4be794fa782dbb8c2dff643ebd239d368c466090b2f7fe2025cf953c27048a8360c24429896a41a538219f632908cdffdbaea56bd810ef
checksums.yaml.gz.sig ADDED
@@ -0,0 +1 @@
1
+ �����9�4�~�o,�"�W��������(z��6;�:#�x�9�ƺ %�h�'�_P��u�����[�V �'��j�A~}��؟�_��Wq��QE�IfQ�W֪a�\�1ߛ���Z���0�}����Aܙ9�y^6��v�j�CM{|�؂��&����%ddB�m���y���-�ۗS��y�eW��͞i r~�_-�Y,ط�9 ;)��H��`[�1B���)=�E�s��ř�0k��
data.tar.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ ��Ƿ��C`K_�8�yʭ-��k��&RZ�#���e����$��hn�x�I0�������dF~SbS7���כnj�,����@���NU�N��}w��{)��A�1y��?�ˢ���dNkL뒂��HC/�J�˃���ޅ��{w:5��TL2*�K����ǒ���?�y]=z�z�� �ݯjKv�,
2
+ �j�<5�*��!�g���71�_�ћ3M�40�{;4���P�΄F�v�c�͜-|��8x�K
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in swagger-docs.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Rich Hollis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,334 @@
1
+ # Swagger::Docs
2
+
3
+ Generates swagger-ui json files for rails apps with APIs. You add the swagger DSL to your controller classes and then run one rake task to generate the json files.
4
+
5
+ Here is an extract of the DSL from a user controller API class:
6
+
7
+ ```
8
+ swagger_controller :users, "User Management"
9
+
10
+ swagger_api :index do
11
+ summary "Fetches all User items"
12
+ param :query, :page, :integer, :optional, "Page number"
13
+ response :unauthorized
14
+ response :not_acceptable
15
+ response :requested_range_not_satisfiable
16
+ end
17
+ ```
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'swagger-docs'
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install swagger-docs
32
+
33
+ ## Usage
34
+
35
+ ### Create Initializer
36
+
37
+ Create an initializer in config/initializers (e.g. swagger_docs.rb) and define your APIs:
38
+
39
+ ```
40
+ Swagger::Docs::Config.register_apis({
41
+ "1.0" => {:controller_base_path => "api/v1", :api_file_path => "public/api/v1/"}
42
+ })
43
+ ```
44
+
45
+ ### Documenting a controller
46
+
47
+ ```
48
+ class Api::V1::UsersController < ApiController
49
+
50
+ swagger_controller :users, "User Management"
51
+
52
+ swagger_api :index do
53
+ summary "Fetches all User items"
54
+ param :query, :page, :integer, :optional, "Page number"
55
+ response :unauthorized
56
+ response :not_acceptable
57
+ response :requested_range_not_satisfiable
58
+ end
59
+
60
+ swagger_api :show do
61
+ summary "Fetches a single User item"
62
+ param :path, :id, :integer, :optional, "User Id"
63
+ response :unauthorized
64
+ response :not_acceptable
65
+ response :not_found
66
+ end
67
+
68
+ swagger_api :create do
69
+ summary "Creates a new User"
70
+ param :form, :first_name, :string, :required, "First name"
71
+ param :form, :last_name, :string, :required, "Last name"
72
+ param :form, :email, :string, :required, "Email address"
73
+ response :unauthorized
74
+ response :not_acceptable
75
+ end
76
+
77
+ swagger_api :update do
78
+ summary "Updates an existing User"
79
+ param :path, :id, :integer, :required, "User Id"
80
+ param :form, :first_name, :string, :optional, "First name"
81
+ param :form, :last_name, :string, :optional, "Last name"
82
+ param :form, :email, :string, :optional, "Email address"
83
+ response :unauthorized
84
+ response :not_found
85
+ response :not_acceptable
86
+ end
87
+
88
+ swagger_api :destroy do
89
+ summary "Deletes an existing User item"
90
+ param :path, :id, :integer, :optional, "User Id"
91
+ response :unauthorized
92
+ response :not_found
93
+ end
94
+
95
+ end
96
+ ```
97
+
98
+ ### Run rake task to generate docs
99
+
100
+ ```
101
+ rake swagger:docs
102
+ ```
103
+
104
+ ### Swagger-ui JSON files should now be present in your api_file_path (e.g. ./public/api/v1)
105
+
106
+ api-docs.json output:
107
+
108
+
109
+ ```
110
+ {
111
+ "apiVersion": "1.0",
112
+ "swaggerVersion": "1.2",
113
+ "basePath": "/api/v1",
114
+ "apis": [
115
+ {
116
+ "path": "/users.{format}",
117
+ "description": "User Management"
118
+ }
119
+ ]
120
+ }
121
+ ```
122
+
123
+ users.json output:
124
+
125
+ ```
126
+ {
127
+ "apiVersion": "1.0",
128
+ "swaggerVersion": "1.2",
129
+ "basePath": "/api/v1",
130
+ "resourcePath": "/users",
131
+ "apis": [
132
+ {
133
+ "path": "/users",
134
+ "operations": [
135
+ {
136
+ "summary": "Fetches all User items",
137
+ "parameters": [
138
+ {
139
+ "paramType": "query",
140
+ "name": "page",
141
+ "type": "integer",
142
+ "description": "Page number",
143
+ "required": false
144
+ }
145
+ ],
146
+ "responseMessages": [
147
+ {
148
+ "code": 401,
149
+ "message": "Unauthorized"
150
+ },
151
+ {
152
+ "code": 406,
153
+ "message": "Not Acceptable"
154
+ },
155
+ {
156
+ "code": 416,
157
+ "message": "Requested Range Not Satisfiable"
158
+ }
159
+ ],
160
+ "method": "get",
161
+ "nickname": "Api::V1::Users#index"
162
+ }
163
+ ]
164
+ },
165
+ {
166
+ "path": "/users",
167
+ "operations": [
168
+ {
169
+ "summary": "Creates a new User",
170
+ "parameters": [
171
+ {
172
+ "paramType": "form",
173
+ "name": "first_name",
174
+ "type": "string",
175
+ "description": "First name",
176
+ "required": true
177
+ },
178
+ {
179
+ "paramType": "form",
180
+ "name": "last_name",
181
+ "type": "string",
182
+ "description": "Last name",
183
+ "required": true
184
+ },
185
+ {
186
+ "paramType": "form",
187
+ "name": "email",
188
+ "type": "string",
189
+ "description": "Email address",
190
+ "required": true
191
+ }
192
+ ],
193
+ "responseMessages": [
194
+ {
195
+ "code": 401,
196
+ "message": "Unauthorized"
197
+ },
198
+ {
199
+ "code": 406,
200
+ "message": "Not Acceptable"
201
+ }
202
+ ],
203
+ "method": "post",
204
+ "nickname": "Api::V1::Users#create"
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ "path": "/users/{id}",
210
+ "operations": [
211
+ {
212
+ "summary": "Fetches a single User item",
213
+ "parameters": [
214
+ {
215
+ "paramType": "path",
216
+ "name": "id",
217
+ "type": "integer",
218
+ "description": "User Id",
219
+ "required": false
220
+ }
221
+ ],
222
+ "responseMessages": [
223
+ {
224
+ "code": 401,
225
+ "message": "Unauthorized"
226
+ },
227
+ {
228
+ "code": 404,
229
+ "message": "Not Found"
230
+ },
231
+ {
232
+ "code": 406,
233
+ "message": "Not Acceptable"
234
+ }
235
+ ],
236
+ "method": "get",
237
+ "nickname": "Api::V1::Users#show"
238
+ }
239
+ ]
240
+ },
241
+ {
242
+ "path": "/users/{id}",
243
+ "operations": [
244
+ {
245
+ "summary": "Updates an existing User",
246
+ "parameters": [
247
+ {
248
+ "paramType": "path",
249
+ "name": "id",
250
+ "type": "integer",
251
+ "description": "User Id",
252
+ "required": true
253
+ },
254
+ {
255
+ "paramType": "form",
256
+ "name": "first_name",
257
+ "type": "string",
258
+ "description": "First name",
259
+ "required": false
260
+ },
261
+ {
262
+ "paramType": "form",
263
+ "name": "last_name",
264
+ "type": "string",
265
+ "description": "Last name",
266
+ "required": false
267
+ },
268
+ {
269
+ "paramType": "form",
270
+ "name": "email",
271
+ "type": "string",
272
+ "description": "Email address",
273
+ "required": false
274
+ }
275
+ ],
276
+ "responseMessages": [
277
+ {
278
+ "code": 401,
279
+ "message": "Unauthorized"
280
+ },
281
+ {
282
+ "code": 404,
283
+ "message": "Not Found"
284
+ },
285
+ {
286
+ "code": 406,
287
+ "message": "Not Acceptable"
288
+ }
289
+ ],
290
+ "method": "put",
291
+ "nickname": "Api::V1::Users#update"
292
+ }
293
+ ]
294
+ },
295
+ {
296
+ "path": "/users/{id}",
297
+ "operations": [
298
+ {
299
+ "summary": "Deletes an existing User item",
300
+ "parameters": [
301
+ {
302
+ "paramType": "path",
303
+ "name": "id",
304
+ "type": "integer",
305
+ "description": "User Id",
306
+ "required": false
307
+ }
308
+ ],
309
+ "responseMessages": [
310
+ {
311
+ "code": 401,
312
+ "message": "Unauthorized"
313
+ },
314
+ {
315
+ "code": 404,
316
+ "message": "Not Found"
317
+ }
318
+ ],
319
+ "method": "delete",
320
+ "nickname": "Api::V1::Users#destroy"
321
+ }
322
+ ]
323
+ }
324
+ ]
325
+ }
326
+ ```
327
+
328
+ ## Contributing
329
+
330
+ 1. Fork it
331
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
332
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
333
+ 4. Push to the branch (`git push origin my-new-feature`)
334
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApyaWNo
3
+ aG9sbGlzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
4
+ b20wHhcNMTMxMDIyMTMwMzI3WhcNMTQxMDIyMTMwMzI3WjBBMRMwEQYDVQQDDApy
5
+ aWNoaG9sbGlzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
6
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDppQTU++yinAuC
7
+ ydu87c/vDGTmE5Go9/zI48/T0kTco+JbUn4BPUaK0DWCEpZULvqwQAqVQm8JQnIU
8
+ 6Z3k1tAQbhtgbG2oWNIxyC7SyXMQw/ag5qoAhw6k3DFE+jGKrREzADFb7vG+nPYp
9
+ 4yinx27jCTIAv7/z2AVt6HoHOYh1s0HniJQWCebi7QgNXboMY8MpFxSwNkcFjl14
10
+ KMSf9SX7iOyiwqgcJmN0fN4be8pH5j/EdinUL1rWlwldcUo2+6LChBswRPmtdaZv
11
+ UyICuX5VfVJA0KrA/ihIMLaZVO5esFso+YrpP+QgbvhLwhn5e/sB5dr3a+y0+GJZ
12
+ zPGtm60bAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
13
+ BBShIiKLL1E1JG++RUVAOSPO7rZV0TAfBgNVHREEGDAWgRRyaWNoaG9sbGlzQGdt
14
+ YWlsLmNvbTAfBgNVHRIEGDAWgRRyaWNoaG9sbGlzQGdtYWlsLmNvbTANBgkqhkiG
15
+ 9w0BAQUFAAOCAQEAe4P1TzJlVhUn60Wx/431wNnuHZS9K4gSzmNr4zuZU6lP3rxx
16
+ rMsSY1nJY1nTBqX9W62hO+KS14ncbZvNU59ao5YVXHDflEB3Yz20DP9E2Uws64Bx
17
+ ify0Dwuq4VV2PiQbczuTGhGupzQpkMttWNZqVdjDbH5k8sGx3MumNX7YUJwUerhZ
18
+ bTBme5soNyJzAeWBqCBPT9p98rC6vqhcBfAVF6RbERYL6MPyoBZWqGeuMR4H2X/v
19
+ RYcsqDfanYBx7QcftOnbeQq7/Ep7Zx+W9+Ph3TiJLMLdAr7bLkgN1SjvrjTL5mQR
20
+ FuQtYvE4LKiUQpG7vLTRB78dQBlSj9fnv2OM9w==
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,12 @@
1
+ require "swagger/docs/config"
2
+ require "swagger/docs/dsl"
3
+ require "swagger/docs/generator"
4
+ require "swagger/docs/impotent_methods"
5
+ require "swagger/docs/methods"
6
+ require "swagger/docs/task"
7
+ require "swagger/docs/version"
8
+
9
+ module Swagger
10
+ module Docs
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Swagger
2
+ module Docs
3
+ class Config
4
+ class << self
5
+ def register_apis(versions)
6
+ ApplicationController.send(:include, ImpotentMethods)
7
+ @versions = versions
8
+ end
9
+ def registered_apis
10
+ @versions ||= {}
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ module Swagger
2
+ module Docs
3
+ class SwaggerDSL
4
+ # http://stackoverflow.com/questions/5851127/change-the-context-binding-inside-a-block-in-ruby/5851325#5851325
5
+ def self.call(action, caller, &blk)
6
+ # Create a new CommandDSL instance, and instance_eval the block to it
7
+ instance = new
8
+ instance.instance_eval(&blk)
9
+ # Now return all of the set instance variables as a Hash
10
+ instance.instance_variables.inject({}) { |result_hash, instance_variable|
11
+ result_hash[instance_variable] = instance.instance_variable_get(instance_variable)
12
+ result_hash # Gotta have the block return the result_hash
13
+ }
14
+ end
15
+
16
+ def summary(text)
17
+ @summary = text
18
+ end
19
+
20
+ def method(method)
21
+ @method = method
22
+ end
23
+
24
+ def type(type)
25
+ @type = type
26
+ end
27
+
28
+ def nickname(nickname)
29
+ @nickname = nickname
30
+ end
31
+
32
+ def parameters
33
+ @parameters ||= []
34
+ end
35
+
36
+ def param(param_type, name, type, required, description = nil, hash={})
37
+ parameters << {:param_type => param_type, :name => name, :type => type,
38
+ :description => description, :required => required == :required ? true : false}.merge(hash)
39
+ end
40
+
41
+ def response_messages
42
+ @response_messages ||= []
43
+ end
44
+
45
+ def response(status, text = nil, model = nil)
46
+ if status.is_a? Symbol
47
+ status_code = Rack::Utils.status_code(status)
48
+ response_messages << {:code => status_code, :message => status.to_s.titleize}
49
+ else
50
+ response_messages << {:code => status, :message => text}
51
+ end
52
+ response_messages.sort_by!{|i| i[:code]}
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,93 @@
1
+ module Swagger
2
+ module Docs
3
+ class Generator
4
+ class << self
5
+
6
+ def camelize_keys_deep!(h)
7
+ h.keys.each do |k|
8
+ ks = k.to_s.camelize(:lower)
9
+ h[ks] = h.delete k
10
+ camelize_keys_deep! h[ks] if h[ks].kind_of? Hash
11
+ if h[ks].kind_of? Array
12
+ h[ks].each do |a|
13
+ next unless a.kind_of? Hash
14
+ camelize_keys_deep! a
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def get_api_path(spec)
21
+ path_api = spec.to_s.gsub("(.:format)", "")
22
+ parts_new = []
23
+ path_api.split("/").each do |path_part|
24
+ part = path_part
25
+ if part[0] == ":"
26
+ part[0] = "{"
27
+ part << "}"
28
+ end
29
+ parts_new << part
30
+ end
31
+ path_api = parts_new*"/"
32
+ end
33
+
34
+ def set_real_methods
35
+ ApplicationController.send(:include, Methods) # replace impotent methods with live ones
36
+ end
37
+
38
+ def write_docs(apis)
39
+ results = {}
40
+ set_real_methods
41
+ Config.registered_apis.each do |api_version,config|
42
+ results[api_version] = write_doc(api_version, config)
43
+ end
44
+ results
45
+ end
46
+
47
+ def write_doc(api_version, config)
48
+ base_path = config[:controller_base_path]
49
+ api_file_path = config[:api_file_path]
50
+ results = {:processed => [], :skipped => []}
51
+
52
+ FileUtils.mkdir_p(api_file_path) # recursively create out output path
53
+ Dir.foreach(api_file_path) {|f| fn = File.join(api_file_path, f); File.delete(fn) if !File.directory?(fn)} # clean output path
54
+
55
+ header = { :api_version => api_version, :swagger_version => "1.2", :base_path => "/#{base_path}"}
56
+ resources = header.merge({:apis => []})
57
+
58
+ paths = Rails.application.routes.routes.map{|i| "#{i.defaults[:controller]}" }
59
+ paths = paths.uniq.select{|i| i.start_with?(base_path)}
60
+ paths.each do |path|
61
+ klass = "#{path.to_s.camelize}Controller".constantize
62
+ if !klass.methods.include?(:swagger_config) or !klass.swagger_config[:controller]
63
+ results[:skipped] << path
64
+ next
65
+ end
66
+ apis = []
67
+ Rails.application.routes.routes.select{|i| i.defaults[:controller] == path}.each do |route|
68
+ action = route.defaults[:action]
69
+ verb = route.verb.source.to_s.delete('$'+'^').downcase.to_sym
70
+ next if !operations = klass.swagger_actions[action.to_sym]
71
+ operations = Hash[operations.map {|k, v| [k.to_s.gsub("@","").to_sym, v] }] # rename :@instance hash keys
72
+ operations[:method] = verb
73
+ operations[:nickname] = "#{path.camelize}##{action}"
74
+ apis << {:path => get_api_path(route.path.spec).gsub("/#{base_path}",""), :operations => [operations]}
75
+ end
76
+ demod = "#{path.to_s.camelize}".demodulize.camelize.underscore
77
+ resource = header.merge({:resource_path => "/#{demod}", :apis => apis})
78
+ camelize_keys_deep!(resource)
79
+ # write controller resource file
80
+ File.open("#{api_file_path}#{demod}.json", 'w') { |file| file.write(resource.to_json) }
81
+ # append resource to resources array (for writing out at end)
82
+ resources[:apis] << {path: "/#{demod}.{format}", description: klass.swagger_config[:description]}
83
+ results[:processed] << path
84
+ end
85
+ # write master resource file
86
+ camelize_keys_deep!(resources)
87
+ File.open("#{api_file_path}api-docs.json", 'w') { |file| file.write(resources.to_json) }
88
+ results
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,21 @@
1
+ module Swagger
2
+ module Docs
3
+ module ImpotentMethods
4
+
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ private
11
+
12
+ def swagger_api(action, &block)
13
+ end
14
+
15
+ def swagger_controller(controller, description)
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ module Swagger
2
+ module Docs
3
+ module Methods
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def swagger_controller(controller, description)
10
+ swagger_config[:controller] = controller
11
+ swagger_config[:description] = description
12
+ end
13
+
14
+ def swagger_model(model)
15
+ swagger_config[:model] = model
16
+ end
17
+
18
+ def swagger_actions
19
+ @swagger_dsl
20
+ end
21
+
22
+ def swagger_config
23
+ @swagger_config ||= {}
24
+ end
25
+
26
+ private
27
+
28
+ def swagger_api(action, &block)
29
+ @swagger_dsl ||= {}
30
+ controller_action = "#{name}##{action} #{self.class}"
31
+ return if @swagger_dsl[action]
32
+ route = Rails.application.routes.routes.select{|i| "#{i.defaults[:controller].to_s.camelize}Controller##{i.defaults[:action]}" == controller_action }.first
33
+ dsl = SwaggerDSL.call(action, self, &block)
34
+ @swagger_dsl[action] = dsl
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module Swagger
2
+ module Docs
3
+ class Task < Rails::Railtie
4
+ rake_tasks do
5
+ Dir[File.join(File.dirname(__FILE__),'../../tasks/*.rake')].each { |f| load f }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Swagger
2
+ module Docs
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ namespace :swagger do
2
+
3
+ desc "Generate Swagger documentation files"
4
+ task :docs => [:environment] do |t,args|
5
+ results = Swagger::Docs::Generator.write_docs(Swagger::Docs::Config.registered_apis)
6
+ results.each do |k,v|
7
+ puts "#{k}: #{v[:processed].count} processed / #{v[:skipped].count} skipped"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationController
2
+
3
+ end
@@ -0,0 +1,6 @@
1
+ module Api
2
+ module V1
3
+ class IgnoredController
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,52 @@
1
+ module Api
2
+ module V1
3
+ class SampleController < ApplicationController
4
+
5
+ swagger_controller :users, "User Management"
6
+
7
+ swagger_api :index do
8
+ summary "Fetches all User items"
9
+ param :query, :page, :integer, :optional, "Page number"
10
+ response :unauthorized
11
+ response :not_acceptable
12
+ response :requested_range_not_satisfiable
13
+ end
14
+
15
+ swagger_api :show do
16
+ summary "Fetches a single User item"
17
+ param :path, :id, :integer, :optional, "User Id"
18
+ response :unauthorized
19
+ response :not_acceptable
20
+ response :not_found
21
+ end
22
+
23
+ swagger_api :create do
24
+ summary "Creates a new User"
25
+ param :form, :first_name, :string, :required, "First name"
26
+ param :form, :last_name, :string, :required, "Last name"
27
+ param :form, :email, :string, :required, "Email address"
28
+ response :unauthorized
29
+ response :not_acceptable
30
+ end
31
+
32
+ swagger_api :update do
33
+ summary "Updates an existing User"
34
+ param :path, :id, :integer, :required, "User Id"
35
+ param :form, :first_name, :string, :optional, "First name"
36
+ param :form, :last_name, :string, :optional, "Last name"
37
+ param :form, :email, :string, :optional, "Email address"
38
+ response :unauthorized
39
+ response :not_found
40
+ response :not_acceptable
41
+ end
42
+
43
+ swagger_api :destroy do
44
+ summary "Deletes an existing User item"
45
+ param :path, :id, :integer, :optional, "User Id"
46
+ response :unauthorized
47
+ response :not_found
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec_helper'
2
+
3
+ describe Swagger::Docs::Generator do
4
+
5
+ require "fixtures/controllers/application_controller"
6
+ require "fixtures/controllers/ignored_controller"
7
+
8
+ def stub_route(verb, action, controller, spec)
9
+ double("route", :verb => double("verb", :source => verb),
10
+ :defaults => {:action => action, :controller => controller},
11
+ :path => double("path", :spec => spec)
12
+ )
13
+ end
14
+
15
+ before(:each) do
16
+ FileUtils.rm_rf(TMP_DIR)
17
+ routes = [
18
+ stub_route("^GET$", "index", "api/v1/ignored", "/api/v1/ignored(.:format)"),
19
+ stub_route("^GET$", "index", "api/v1/sample", "/api/v1/sample(.:format)"),
20
+ stub_route("^POST$", "create", "api/v1/sample", "/api/v1/sample(.:format)"),
21
+ stub_route("^GET$", "show", "api/v1/sample", "/api/v1/sample/:id(.:format)"),
22
+ stub_route("^PUT$", "update", "api/v1/sample", "/api/v1/sample/:id(.:format)"),
23
+ stub_route("^DELETE$", "destroy", "api/v1/sample", "/api/v1/sample/:id(.:format)")
24
+ ]
25
+ @config = Swagger::Docs::Config.register_apis({
26
+ "1.0" => {:controller_base_path => "api/v1", :api_file_path => "#{TMP_DIR}api/v1/"}
27
+ })
28
+ Rails.stub_chain(:application, :routes, :routes).and_return(routes)
29
+ Swagger::Docs::Generator.set_real_methods
30
+ require "fixtures/controllers/sample_controller"
31
+ end
32
+
33
+ context "test suite initialization" do
34
+ it "the resources file does not exist" do
35
+ expect(File.exists?(FILE_RESOURCES)).to be_false
36
+ end
37
+ it "the resource file does not exist" do
38
+ expect(File.exists?(FILE_RESOURCE)).to be_false
39
+ end
40
+ end
41
+
42
+ describe "#write_docs" do
43
+ let(:generate) { Swagger::Docs::Generator::write_docs(@config) }
44
+ before(:each) do
45
+ generate
46
+ end
47
+ it "writes the resources file" do
48
+ expect(File.exists?(FILE_RESOURCES)).to be_true
49
+ end
50
+ it "writes the resource file" do
51
+ expect(File.exists?(FILE_RESOURCE)).to be_true
52
+ end
53
+ it "returns results hash" do
54
+ results = generate
55
+ expect(results["1.0"][:processed].count).to eq 1
56
+ expect(results["1.0"][:skipped].count).to eq 1
57
+ end
58
+ context "resources files" do
59
+ let(:resources) { File.read(FILE_RESOURCES)}
60
+ let(:response) { JSON.parse(resources) }
61
+ it "writes version correctly" do
62
+ expect(response["apiVersion"]).to eq "1.0"
63
+ end
64
+ it "writes swaggerVersion correctly" do
65
+ expect(response["swaggerVersion"]).to eq "1.2"
66
+ end
67
+ it "writes basePath correctly" do
68
+ expect(response["basePath"]).to eq "/api/v1"
69
+ end
70
+ it "writes apis correctly" do
71
+ expect(response["apis"].count).to eq 1
72
+ end
73
+ it "writes api path correctly" do
74
+ expect(response["apis"][0]["path"]).to eq "/sample.{format}"
75
+ end
76
+ it "writes api description correctly" do
77
+ expect(response["apis"][0]["description"]).to eq "User Management"
78
+ end
79
+ end
80
+ context "resource file" do
81
+ let(:resource) { File.read(FILE_RESOURCE)}
82
+ let(:response) { JSON.parse(resource) }
83
+ let(:first) { response["apis"].first }
84
+ let(:operations) { first["operations"] }
85
+ let(:params) { operations.first["parameters"] }
86
+ let(:response_msgs) { operations.first["responseMessages"] }
87
+ # {"apiVersion":"1.0","swaggerVersion":"1.2","basePath":"/api/v1","resourcePath":"/sample"
88
+ it "writes version correctly" do
89
+ expect(response["apiVersion"]).to eq "1.0"
90
+ end
91
+ it "writes swaggerVersion correctly" do
92
+ expect(response["swaggerVersion"]).to eq "1.2"
93
+ end
94
+ it "writes basePath correctly" do
95
+ expect(response["basePath"]).to eq "/api/v1"
96
+ end
97
+ it "writes resourcePath correctly" do
98
+ expect(response["resourcePath"]).to eq "/sample"
99
+ end
100
+ it "writes out expected api count" do
101
+ expect(response["apis"].count).to eq 5
102
+ end
103
+ context "first api" do
104
+ #"apis":[{"path":" /sample","operations":[{"summary":"Fetches all User items"
105
+ #,"method":"get","nickname":"Api::V1::Sample#index"}]
106
+ it "writes path correctly" do
107
+ expect(first["path"]).to eq "/sample"
108
+ end
109
+ it "writes summary correctly" do
110
+ expect(operations.first["summary"]).to eq "Fetches all User items"
111
+ end
112
+ it "writes method correctly" do
113
+ expect(operations.first["method"]).to eq "get"
114
+ end
115
+ it "writes nickname correctly" do
116
+ expect(operations.first["nickname"]).to eq "Api::V1::Sample#index"
117
+ end
118
+ #"parameters":[{"paramType":"query","name":"page","type":"integer","description":"Page number","required":false}]
119
+ context "parameters" do
120
+ it "has correct count" do
121
+ expect(params.count).to eq 1
122
+ end
123
+ it "writes paramType correctly" do
124
+ expect(params.first["paramType"]).to eq "query"
125
+ end
126
+ it "writes name correctly" do
127
+ expect(params.first["name"]).to eq "page"
128
+ end
129
+ it "writes type correctly" do
130
+ expect(params.first["type"]).to eq "integer"
131
+ end
132
+ it "writes description correctly" do
133
+ expect(params.first["description"]).to eq "Page number"
134
+ end
135
+ it "writes required correctly" do
136
+ expect(params.first["required"]).to be_false
137
+ end
138
+ end
139
+ #"responseMessages":[{"code":401,"message":"Unauthorized"},{"code":406,"message":"Not Acceptable"},{"code":416,"message":"Requested Range Not Satisfiable"}]
140
+ context "response messages" do
141
+ it "has correct count" do
142
+ expect(response_msgs.count).to eq 3
143
+ end
144
+ it "writes code correctly" do
145
+ expect(response_msgs.first["code"]).to eq 401
146
+ end
147
+ it "writes message correctly" do
148
+ expect(response_msgs.first["message"]).to eq "Unauthorized"
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,16 @@
1
+ require "rails"
2
+ require "swagger/docs"
3
+ require "ostruct"
4
+ require "json"
5
+
6
+ TMP_DIR = "/tmp/swagger-docs/"
7
+ TMP_API_DIR = "/tmp/swagger-docs/api/v1/"
8
+ FILE_RESOURCES = "#{TMP_API_DIR}api-docs.json"
9
+ FILE_RESOURCE = "#{TMP_API_DIR}sample.json"
10
+
11
+ RSpec.configure do |config|
12
+ config.expect_with :rspec do |c|
13
+ c.syntax = :expect
14
+ end
15
+ config.color_enabled = true
16
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'swagger/docs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "swagger-docs"
8
+ spec.version = Swagger::Docs::VERSION
9
+ spec.authors = ["Rich Hollis"]
10
+ spec.email = ["richhollis@gmail.com"]
11
+ spec.description = %q{Generates json files for rails apps to use with swagger-ui}
12
+ spec.summary = %q{Generates swagger-ui json files for rails apps with APIs. You add the swagger DSL to your controller classes and then run one rake task to generate the json files.
13
+ }
14
+ spec.homepage = "https://github.com/richhollis/swagger-docs"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.cert_chain = ['certs/gem-public_cert.pem']
23
+ spec.signing_key = File.expand_path("~/.gemcert/gem-private_key.pem") if $0 =~ /gem\z/
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "rails"
29
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swagger-docs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rich Hollis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApyaWNo
14
+ aG9sbGlzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
15
+ b20wHhcNMTMxMDIyMTMwMzI3WhcNMTQxMDIyMTMwMzI3WjBBMRMwEQYDVQQDDApy
16
+ aWNoaG9sbGlzMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
17
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDppQTU++yinAuC
18
+ ydu87c/vDGTmE5Go9/zI48/T0kTco+JbUn4BPUaK0DWCEpZULvqwQAqVQm8JQnIU
19
+ 6Z3k1tAQbhtgbG2oWNIxyC7SyXMQw/ag5qoAhw6k3DFE+jGKrREzADFb7vG+nPYp
20
+ 4yinx27jCTIAv7/z2AVt6HoHOYh1s0HniJQWCebi7QgNXboMY8MpFxSwNkcFjl14
21
+ KMSf9SX7iOyiwqgcJmN0fN4be8pH5j/EdinUL1rWlwldcUo2+6LChBswRPmtdaZv
22
+ UyICuX5VfVJA0KrA/ihIMLaZVO5esFso+YrpP+QgbvhLwhn5e/sB5dr3a+y0+GJZ
23
+ zPGtm60bAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
24
+ BBShIiKLL1E1JG++RUVAOSPO7rZV0TAfBgNVHREEGDAWgRRyaWNoaG9sbGlzQGdt
25
+ YWlsLmNvbTAfBgNVHRIEGDAWgRRyaWNoaG9sbGlzQGdtYWlsLmNvbTANBgkqhkiG
26
+ 9w0BAQUFAAOCAQEAe4P1TzJlVhUn60Wx/431wNnuHZS9K4gSzmNr4zuZU6lP3rxx
27
+ rMsSY1nJY1nTBqX9W62hO+KS14ncbZvNU59ao5YVXHDflEB3Yz20DP9E2Uws64Bx
28
+ ify0Dwuq4VV2PiQbczuTGhGupzQpkMttWNZqVdjDbH5k8sGx3MumNX7YUJwUerhZ
29
+ bTBme5soNyJzAeWBqCBPT9p98rC6vqhcBfAVF6RbERYL6MPyoBZWqGeuMR4H2X/v
30
+ RYcsqDfanYBx7QcftOnbeQq7/Ep7Zx+W9+Ph3TiJLMLdAr7bLkgN1SjvrjTL5mQR
31
+ FuQtYvE4LKiUQpG7vLTRB78dQBlSj9fnv2OM9w==
32
+ -----END CERTIFICATE-----
33
+ date: 2013-10-22 00:00:00.000000000 Z
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: bundler
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '1.3'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '1.3'
49
+ - !ruby/object:Gem::Dependency
50
+ name: rake
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: rspec
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ - !ruby/object:Gem::Dependency
78
+ name: rails
79
+ requirement: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ type: :development
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ description: Generates json files for rails apps to use with swagger-ui
92
+ email:
93
+ - richhollis@gmail.com
94
+ executables: []
95
+ extensions: []
96
+ extra_rdoc_files: []
97
+ files:
98
+ - .gitignore
99
+ - Gemfile
100
+ - LICENSE.txt
101
+ - README.md
102
+ - Rakefile
103
+ - certs/gem-public_cert.pem
104
+ - lib/swagger/docs.rb
105
+ - lib/swagger/docs/config.rb
106
+ - lib/swagger/docs/dsl.rb
107
+ - lib/swagger/docs/generator.rb
108
+ - lib/swagger/docs/impotent_methods.rb
109
+ - lib/swagger/docs/methods.rb
110
+ - lib/swagger/docs/task.rb
111
+ - lib/swagger/docs/version.rb
112
+ - lib/tasks/swagger.rake
113
+ - spec/fixtures/controllers/application_controller.rb
114
+ - spec/fixtures/controllers/ignored_controller.rb
115
+ - spec/fixtures/controllers/sample_controller.rb
116
+ - spec/lib/swagger/docs/generator_spec.rb
117
+ - spec/spec_helper.rb
118
+ - swagger-docs.gemspec
119
+ homepage: https://github.com/richhollis/swagger-docs
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.0.6
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Generates swagger-ui json files for rails apps with APIs. You add the swagger
143
+ DSL to your controller classes and then run one rake task to generate the json files.
144
+ test_files:
145
+ - spec/fixtures/controllers/application_controller.rb
146
+ - spec/fixtures/controllers/ignored_controller.rb
147
+ - spec/fixtures/controllers/sample_controller.rb
148
+ - spec/lib/swagger/docs/generator_spec.rb
149
+ - spec/spec_helper.rb
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ O94�Mt�!<�"����w�3w��pPԢ�F׺K�P^�оO��qȡL��Kݗ�&�1>]$.�O_�F����QI7-��/��b��L�$���>n:��,1�?���`�됬i��qQ4���2>zY��v^���}j�~m�K���<X�� CѴ#�a��
2
+ f�hAsiZ�0ֿx���� #��� ��03�UTF���_��:��Zs�[#�\sw;-h