swagger-docs 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8288447cb546d04ee3e791e473f06351c1f9e702
4
- data.tar.gz: cf69d2574759663cdccb895d4c320c0b085fa0e4
3
+ metadata.gz: 93662e19d54d8714102ecfbd08e1ca88e360cd00
4
+ data.tar.gz: 646f03361ada42fc36e8369bc602e00307b86b0d
5
5
  SHA512:
6
- metadata.gz: 0cfdeb3b6ffc0c27f2306739d7831496c65c480efd54ad583923b5c0d1a5e6aa12643f55e59ffe4797e71b87f7d29fdba49c8f5d866f167906cc1e113f4be7a1
7
- data.tar.gz: aa89d0b6b9cac77cd1b9ab5e952b89ce3c85bed99fdc0933e891ba9bcf633180ffc72e6e1ba82e1dfbb197fdb261efafbdc66970f83dbfe474073894716aa6f2
6
+ metadata.gz: 868a3e56fc30ccee2ee8e636ab800d21398f4d5f4b0d8bf7867a302471e9c66841841a2332159f4e61a8311852b6bf9d437ff6135d685d60e6f04abedc0d2aad
7
+ data.tar.gz: 709e92e1acbee458adfd53facc2f2be17308f6dfca0bfd7a6213eceb232d447686e8aea79d16a7d4e3e4f2e8c874e1b8a23ed2e6e052f6980cfefe44acfa0008
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -38,14 +38,18 @@ Create an initializer in config/initializers (e.g. swagger_docs.rb) and define y
38
38
 
39
39
  ```
40
40
  Swagger::Docs::Config.register_apis({
41
- "1.0" => {:controller_base_path => "api/v1", :api_file_path => "public/api/v1/", :base_path => "http://api.somedomain.com"}
42
- })
41
+ "1.0" => {
42
+ :api_file_path => "public/api/v1/", # the output location where your .json files are written to
43
+ :base_path => "http://api.somedomain.com", # the URL base path to your API
44
+ :clean_directory => false # if you want to delete all .json files at each generation
45
+ }
46
+ )
43
47
  ```
44
48
 
45
49
  ### Documenting a controller
46
50
 
47
51
  ```
48
- class Api::V1::UsersController < ApiController
52
+ class Api::V1::UsersController < ApplicationController
49
53
 
50
54
  swagger_controller :users, "User Management"
51
55
 
@@ -101,7 +105,15 @@ end
101
105
  rake swagger:docs
102
106
  ```
103
107
 
104
- ### Swagger-ui JSON files should now be present in your api_file_path (e.g. ./public/api/v1)
108
+ Swagger-ui JSON files should now be present in your api_file_path (e.g. ./public/api/v1)
109
+
110
+ ### Sample
111
+
112
+ A sample Rails application where you can run the above rake command and view the output in swagger-ui can be found here:
113
+
114
+ https://github.com/richhollis/swagger-docs-sample
115
+
116
+ ### Output files
105
117
 
106
118
  api-docs.json output:
107
119
 
@@ -18,7 +18,7 @@ module Swagger
18
18
  end
19
19
 
20
20
  def get_api_path(spec)
21
- path_api = spec.to_s.gsub("(.:format)", "")
21
+ path_api = trim_leading_slash(spec.to_s.gsub("(.:format)", ""))
22
22
  parts_new = []
23
23
  path_api.split("/").each do |path_part|
24
24
  part = path_part
@@ -31,6 +31,22 @@ module Swagger
31
31
  path_api = parts_new*"/"
32
32
  end
33
33
 
34
+ def trim_leading_slash(str)
35
+ return str if !str
36
+ return str unless str[0] == '/'
37
+ str[1..-1]
38
+ end
39
+
40
+ def trim_trailing_slash(str)
41
+ return str if !str
42
+ return str unless str[-1] == '/'
43
+ str[0..-2]
44
+ end
45
+
46
+ def trim_slashes(str)
47
+ trim_leading_slash(trim_trailing_slash(str))
48
+ end
49
+
34
50
  def set_real_methods
35
51
  ApplicationController.send(:include, Methods) # replace impotent methods with live ones
36
52
  end
@@ -38,33 +54,44 @@ module Swagger
38
54
  def write_docs(apis)
39
55
  results = {}
40
56
  set_real_methods
41
- Config.registered_apis.each do |api_version,config|
42
- results[api_version] = write_doc(api_version, config)
57
+ unless Config.registered_apis.empty?
58
+ Config.registered_apis.each do |api_version,config|
59
+ results[api_version] = write_doc(api_version, config)
60
+ end
61
+ else
62
+ config = {:api_file_path => "public/", :base_path => "/"}
63
+ puts "No swagger_docs config: Using default config #{config}"
64
+ results["1.0"] = write_doc("1.0", config)
43
65
  end
44
66
  results
45
67
  end
46
68
 
47
69
  def write_doc(api_version, config)
48
- base_path = config[:base_path]
49
- controller_base_path = config[:controller_base_path]
70
+ base_path = trim_trailing_slash(config[:base_path] || "")
71
+ controller_base_path = trim_leading_slash(config[:controller_base_path] || "")
50
72
  api_file_path = config[:api_file_path]
73
+ clean_directory = config[:clean_directory] || false
51
74
  results = {:processed => [], :skipped => []}
52
75
 
76
+ # create output paths
53
77
  FileUtils.mkdir_p(api_file_path) # recursively create out output path
54
- Dir.foreach(api_file_path) {|f| fn = File.join(api_file_path, f); File.delete(fn) if !File.directory?(fn)} # clean output path
78
+ Dir.foreach(api_file_path) {|f| fn = File.join(api_file_path, f); File.delete(fn) if !File.directory?(fn) and File.extname(fn) == '.json'} if clean_directory # clean output path
55
79
 
56
- header = { :api_version => api_version, :swagger_version => "1.2", :base_path => "#{base_path}/#{controller_base_path}"}
80
+ base_path += "/#{controller_base_path}" unless controller_base_path.empty?
81
+ header = { :api_version => api_version, :swagger_version => "1.2", :base_path => base_path + "/"}
57
82
  resources = header.merge({:apis => []})
58
83
 
59
84
  paths = Rails.application.routes.routes.map{|i| "#{i.defaults[:controller]}" }
60
85
  paths = paths.uniq.select{|i| i.start_with?(controller_base_path)}
61
86
  paths.each do |path|
87
+ next if path.empty?
62
88
  klass = "#{path.to_s.camelize}Controller".constantize
63
89
  if !klass.methods.include?(:swagger_config) or !klass.swagger_config[:controller]
64
90
  results[:skipped] << path
65
91
  next
66
92
  end
67
93
  apis = []
94
+ debased_path = path.gsub("#{controller_base_path}", "")
68
95
  Rails.application.routes.routes.select{|i| i.defaults[:controller] == path}.each do |route|
69
96
  action = route.defaults[:action]
70
97
  verb = route.verb.source.to_s.delete('$'+'^').downcase.to_sym
@@ -72,20 +99,20 @@ module Swagger
72
99
  operations = Hash[operations.map {|k, v| [k.to_s.gsub("@","").to_sym, v] }] # rename :@instance hash keys
73
100
  operations[:method] = verb
74
101
  operations[:nickname] = "#{path.camelize}##{action}"
75
- apis << {:path => get_api_path(route.path.spec).gsub("/#{controller_base_path}",""), :operations => [operations]}
102
+ apis << {:path => trim_slashes(get_api_path(trim_leading_slash(route.path.spec.to_s)).gsub("#{controller_base_path}","")), :operations => [operations]}
76
103
  end
77
- demod = "#{path.to_s.camelize}".demodulize.camelize.underscore
78
- resource = header.merge({:resource_path => "/#{demod}", :apis => apis})
104
+ demod = "#{debased_path.to_s.camelize}".demodulize.camelize.underscore
105
+ resource = header.merge({:resource_path => "#{demod}", :apis => apis})
79
106
  camelize_keys_deep!(resource)
80
107
  # write controller resource file
81
- File.open("#{api_file_path}#{demod}.json", 'w') { |file| file.write(resource.to_json) }
108
+ File.open("#{api_file_path}/#{demod}.json", 'w') { |file| file.write(resource.to_json) }
82
109
  # append resource to resources array (for writing out at end)
83
- resources[:apis] << {path: "/#{demod}.{format}", description: klass.swagger_config[:description]}
110
+ resources[:apis] << {path: "#{trim_leading_slash(debased_path)}.{format}", description: klass.swagger_config[:description]}
84
111
  results[:processed] << path
85
112
  end
86
113
  # write master resource file
87
114
  camelize_keys_deep!(resources)
88
- File.open("#{api_file_path}api-docs.json", 'w') { |file| file.write(resources.to_json) }
115
+ File.open("#{api_file_path}/api-docs.json", 'w') { |file| file.write(resources.to_json) }
89
116
  results
90
117
  end
91
118
  end
@@ -1,5 +1,5 @@
1
1
  module Swagger
2
2
  module Docs
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -5,6 +5,10 @@ describe Swagger::Docs::Generator do
5
5
  require "fixtures/controllers/application_controller"
6
6
  require "fixtures/controllers/ignored_controller"
7
7
 
8
+ def generate(config)
9
+ Swagger::Docs::Generator::write_docs(config)
10
+ end
11
+
8
12
  def stub_route(verb, action, controller, spec)
9
13
  double("route", :verb => double("verb", :source => verb),
10
14
  :defaults => {:action => action, :controller => controller},
@@ -14,67 +18,38 @@ describe Swagger::Docs::Generator do
14
18
 
15
19
  before(:each) do
16
20
  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/", :base_path => "http://api.no.where"}
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
21
  end
32
22
 
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
23
+ let(:routes) {[
24
+ stub_route("^GET$", "index", "api/v1/ignored", "/api/v1/ignored(.:format)"),
25
+ stub_route("^GET$", "index", "api/v1/sample", "/api/v1/sample(.:format)"),
26
+ stub_route("^POST$", "create", "api/v1/sample", "/api/v1/sample(.:format)"),
27
+ stub_route("^GET$", "show", "api/v1/sample", "/api/v1/sample/:id(.:format)"),
28
+ stub_route("^PUT$", "update", "api/v1/sample", "/api/v1/sample/:id(.:format)"),
29
+ stub_route("^DELETE$", "destroy", "api/v1/sample", "/api/v1/sample/:id(.:format)")
30
+ ]}
41
31
 
42
- describe "#write_docs" do
43
- let(:generate) { Swagger::Docs::Generator::write_docs(@config) }
32
+ context "without controller base path" do
33
+ let(:config) { Swagger::Docs::Config.register_apis({
34
+ "1.0" => {:api_file_path => "#{TMP_DIR}api/v1/", :base_path => "http://api.no.where"}
35
+ })}
44
36
  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
37
+ Rails.stub_chain(:application, :routes, :routes).and_return(routes)
38
+ Swagger::Docs::Generator.set_real_methods
39
+ require "fixtures/controllers/sample_controller"
40
+ generate(config)
57
41
  end
58
42
  context "resources files" do
59
43
  let(:resources) { File.read(FILE_RESOURCES)}
60
44
  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
45
  it "writes basePath correctly" do
68
- expect(response["basePath"]).to eq "http://api.no.where/api/v1"
46
+ expect(response["basePath"]).to eq "http://api.no.where/"
69
47
  end
70
48
  it "writes apis correctly" do
71
49
  expect(response["apis"].count).to eq 1
72
50
  end
73
51
  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"
52
+ expect(response["apis"][0]["path"]).to eq "api/v1/sample.{format}"
78
53
  end
79
54
  end
80
55
  context "resource file" do
@@ -82,20 +57,12 @@ describe Swagger::Docs::Generator do
82
57
  let(:response) { JSON.parse(resource) }
83
58
  let(:first) { response["apis"].first }
84
59
  let(:operations) { first["operations"] }
85
- let(:params) { operations.first["parameters"] }
86
- let(:response_msgs) { operations.first["responseMessages"] }
87
60
  # {"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
61
  it "writes basePath correctly" do
95
- expect(response["basePath"]).to eq "http://api.no.where/api/v1"
62
+ expect(response["basePath"]).to eq "http://api.no.where/"
96
63
  end
97
64
  it "writes resourcePath correctly" do
98
- expect(response["resourcePath"]).to eq "/sample"
65
+ expect(response["resourcePath"]).to eq "sample"
99
66
  end
100
67
  it "writes out expected api count" do
101
68
  expect(response["apis"].count).to eq 5
@@ -104,48 +71,153 @@ describe Swagger::Docs::Generator do
104
71
  #"apis":[{"path":" /sample","operations":[{"summary":"Fetches all User items"
105
72
  #,"method":"get","nickname":"Api::V1::Sample#index"}]
106
73
  it "writes path correctly" do
107
- expect(first["path"]).to eq "/sample"
74
+ expect(first["path"]).to eq "api/v1/sample"
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ context "with controller base path" do
81
+ let(:config) { Swagger::Docs::Config.register_apis({
82
+ "1.0" => {:controller_base_path => "api/v1", :api_file_path => "#{TMP_DIR}api/v1/", :base_path => "http://api.no.where"}
83
+ })}
84
+ before(:each) do
85
+ Rails.stub_chain(:application, :routes, :routes).and_return(routes)
86
+ Swagger::Docs::Generator.set_real_methods
87
+ require "fixtures/controllers/sample_controller"
88
+ end
89
+
90
+ context "test suite initialization" do
91
+ it "the resources file does not exist" do
92
+ expect(File.exists?(FILE_RESOURCES)).to be_false
93
+ end
94
+ it "the resource file does not exist" do
95
+ expect(File.exists?(FILE_RESOURCE)).to be_false
96
+ end
97
+ end
98
+
99
+ describe "#write_docs" do
100
+ before(:each) do
101
+ generate(config)
102
+ end
103
+ it "cleans json files in directory when set" do
104
+ file_to_delete = "#{TMP_DIR}api/v1/delete_me.json"
105
+ File.open(file_to_delete, 'w') {|f| f.write("{}") }
106
+ expect(File.exists?(file_to_delete)).to be_true
107
+ config["1.0"][:clean_directory] = true
108
+ generate(config)
109
+ expect(File.exists?(file_to_delete)).to be_false
110
+ end
111
+ it "keeps non json files in directory when cleaning" do
112
+ file_to_keep = "#{TMP_DIR}api/v1/keep_me"
113
+ File.open(file_to_keep, 'w') {|f| f.write("{}") }
114
+ config["1.0"][:clean_directory] = true
115
+ generate(config)
116
+ expect(File.exists?(file_to_keep)).to be_true
117
+ end
118
+ it "writes the resources file" do
119
+ expect(File.exists?(FILE_RESOURCES)).to be_true
120
+ end
121
+ it "writes the resource file" do
122
+ expect(File.exists?(FILE_RESOURCE)).to be_true
123
+ end
124
+ it "returns results hash" do
125
+ results = generate(config)
126
+ expect(results["1.0"][:processed].count).to eq 1
127
+ expect(results["1.0"][:skipped].count).to eq 1
128
+ end
129
+ context "resources files" do
130
+ let(:resources) { File.read(FILE_RESOURCES)}
131
+ let(:response) { JSON.parse(resources) }
132
+ it "writes version correctly" do
133
+ expect(response["apiVersion"]).to eq "1.0"
108
134
  end
109
- it "writes summary correctly" do
110
- expect(operations.first["summary"]).to eq "Fetches all User items"
135
+ it "writes swaggerVersion correctly" do
136
+ expect(response["swaggerVersion"]).to eq "1.2"
111
137
  end
112
- it "writes method correctly" do
113
- expect(operations.first["method"]).to eq "get"
138
+ it "writes basePath correctly" do
139
+ expect(response["basePath"]).to eq "http://api.no.where/api/v1/"
114
140
  end
115
- it "writes nickname correctly" do
116
- expect(operations.first["nickname"]).to eq "Api::V1::Sample#index"
141
+ it "writes apis correctly" do
142
+ expect(response["apis"].count).to eq 1
117
143
  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"
144
+ it "writes api path correctly" do
145
+ expect(response["apis"][0]["path"]).to eq "sample.{format}"
146
+ end
147
+ it "writes api description correctly" do
148
+ expect(response["apis"][0]["description"]).to eq "User Management"
149
+ end
150
+ end
151
+ context "resource file" do
152
+ let(:resource) { File.read(FILE_RESOURCE)}
153
+ let(:response) { JSON.parse(resource) }
154
+ let(:first) { response["apis"].first }
155
+ let(:operations) { first["operations"] }
156
+ let(:params) { operations.first["parameters"] }
157
+ let(:response_msgs) { operations.first["responseMessages"] }
158
+ # {"apiVersion":"1.0","swaggerVersion":"1.2","basePath":"/api/v1","resourcePath":"/sample"
159
+ it "writes version correctly" do
160
+ expect(response["apiVersion"]).to eq "1.0"
161
+ end
162
+ it "writes swaggerVersion correctly" do
163
+ expect(response["swaggerVersion"]).to eq "1.2"
164
+ end
165
+ it "writes basePath correctly" do
166
+ expect(response["basePath"]).to eq "http://api.no.where/api/v1/"
167
+ end
168
+ it "writes resourcePath correctly" do
169
+ expect(response["resourcePath"]).to eq "sample"
170
+ end
171
+ it "writes out expected api count" do
172
+ expect(response["apis"].count).to eq 5
173
+ end
174
+ context "first api" do
175
+ #"apis":[{"path":" /sample","operations":[{"summary":"Fetches all User items"
176
+ #,"method":"get","nickname":"Api::V1::Sample#index"}]
177
+ it "writes path correctly" do
178
+ expect(first["path"]).to eq "sample"
131
179
  end
132
- it "writes description correctly" do
133
- expect(params.first["description"]).to eq "Page number"
180
+ it "writes summary correctly" do
181
+ expect(operations.first["summary"]).to eq "Fetches all User items"
134
182
  end
135
- it "writes required correctly" do
136
- expect(params.first["required"]).to be_false
183
+ it "writes method correctly" do
184
+ expect(operations.first["method"]).to eq "get"
137
185
  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
186
+ it "writes nickname correctly" do
187
+ expect(operations.first["nickname"]).to eq "Api::V1::Sample#index"
143
188
  end
144
- it "writes code correctly" do
145
- expect(response_msgs.first["code"]).to eq 401
189
+ #"parameters":[{"paramType":"query","name":"page","type":"integer","description":"Page number","required":false}]
190
+ context "parameters" do
191
+ it "has correct count" do
192
+ expect(params.count).to eq 1
193
+ end
194
+ it "writes paramType correctly" do
195
+ expect(params.first["paramType"]).to eq "query"
196
+ end
197
+ it "writes name correctly" do
198
+ expect(params.first["name"]).to eq "page"
199
+ end
200
+ it "writes type correctly" do
201
+ expect(params.first["type"]).to eq "integer"
202
+ end
203
+ it "writes description correctly" do
204
+ expect(params.first["description"]).to eq "Page number"
205
+ end
206
+ it "writes required correctly" do
207
+ expect(params.first["required"]).to be_false
208
+ end
146
209
  end
147
- it "writes message correctly" do
148
- expect(response_msgs.first["message"]).to eq "Unauthorized"
210
+ #"responseMessages":[{"code":401,"message":"Unauthorized"},{"code":406,"message":"Not Acceptable"},{"code":416,"message":"Requested Range Not Satisfiable"}]
211
+ context "response messages" do
212
+ it "has correct count" do
213
+ expect(response_msgs.count).to eq 3
214
+ end
215
+ it "writes code correctly" do
216
+ expect(response_msgs.first["code"]).to eq 401
217
+ end
218
+ it "writes message correctly" do
219
+ expect(response_msgs.first["message"]).to eq "Unauthorized"
220
+ end
149
221
  end
150
222
  end
151
223
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swagger-docs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rich Hollis
@@ -30,7 +30,7 @@ cert_chain:
30
30
  RYcsqDfanYBx7QcftOnbeQq7/Ep7Zx+W9+Ph3TiJLMLdAr7bLkgN1SjvrjTL5mQR
31
31
  FuQtYvE4LKiUQpG7vLTRB78dQBlSj9fnv2OM9w==
32
32
  -----END CERTIFICATE-----
33
- date: 2013-10-22 00:00:00.000000000 Z
33
+ date: 2013-11-04 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: bundler
metadata.gz.sig CHANGED
Binary file