swagger-docs 0.0.1

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.
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