swagger-blocks 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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/lib/swagger/blocks.rb +403 -0
- data/lib/swagger/blocks/version.rb +5 -0
- data/spec/lib/swagger_api_declaration.json +201 -0
- data/spec/lib/swagger_blocks_spec.rb +371 -0
- data/spec/lib/swagger_resource_listing.json +60 -0
- data/spec/spec_helper.rb +42 -0
- data/swagger-blocks.gemspec +25 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b309bb304d3b80b0a6e213b7f3ec59ae1c9fa51a
|
4
|
+
data.tar.gz: c68fce426638012787fc21ea5f6ee4c514ae4d18
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f4d95e4aedf7c8107d2c09e4c814cdc59c7336e5fb4370e345055fc01de0b7807787d74ca9f6250d4a5f7d6182adb3f7ef0252fe598171c7332d0dfa9490828c
|
7
|
+
data.tar.gz: f419056f5dd26c88d8dafd5f1fcbff859015257897db939ff1d46e13f97e481020362c2db6c948b35a8c80f3a9deb7d6bc21212d262fcdde88c546f5df6e9d10
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
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
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2014 Mike Fotinakis
|
2
|
+
|
3
|
+
The MIT License (MIT)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Swagger::Blocks
|
2
|
+
|
3
|
+
[](https://travis-ci.org/fotinakis/swagger-blocks)
|
4
|
+
|
5
|
+
TODO: Write a gem description
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'swagger-blocks'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install swagger-blocks
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/fotinakis/swagger-blocks/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,403 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'swagger/blocks/version'
|
3
|
+
|
4
|
+
module Swagger
|
5
|
+
module Blocks
|
6
|
+
# Some custom error classes.
|
7
|
+
class Error < Exception; end
|
8
|
+
class DeclarationError < Error; end
|
9
|
+
class NotFoundError < Error; end
|
10
|
+
|
11
|
+
# Inject the swagger_root, swagger_api_root, and swagger_model class methods.
|
12
|
+
def self.included(base)
|
13
|
+
base.extend(ClassMethods)
|
14
|
+
end
|
15
|
+
|
16
|
+
module_function def build_root_json(swaggered_classes)
|
17
|
+
data = Swagger::Blocks::InternalHelpers.parse_swaggered_classes(swaggered_classes)
|
18
|
+
data[:root_node].as_json
|
19
|
+
end
|
20
|
+
|
21
|
+
module_function def build_api_json(resource_name, swaggered_classes)
|
22
|
+
data = Swagger::Blocks::InternalHelpers.parse_swaggered_classes(swaggered_classes)
|
23
|
+
api_node = data[:api_node_map][resource_name.to_sym]
|
24
|
+
raise Swagger::Blocks::NotFoundError.new(
|
25
|
+
"Not found: swagger_api_root named #{resource_name}") if !api_node
|
26
|
+
|
27
|
+
# Aggregate all model definitions into a new ModelsNode tree and add it to the JSON.
|
28
|
+
temp_models_node = Swagger::Blocks::ModelsNode.call(name: 'models') { }
|
29
|
+
data[:models_nodes].each do |models_node|
|
30
|
+
temp_models_node.merge!(models_node)
|
31
|
+
end
|
32
|
+
result = api_node.as_json
|
33
|
+
result.merge!(temp_models_node.as_json) if temp_models_node
|
34
|
+
result
|
35
|
+
end
|
36
|
+
|
37
|
+
module InternalHelpers
|
38
|
+
# Return [root_node, api_node_map] from all of the given swaggered_classes.
|
39
|
+
def self.parse_swaggered_classes(swaggered_classes)
|
40
|
+
root_nodes = []
|
41
|
+
api_node_map = {}
|
42
|
+
models_nodes = []
|
43
|
+
swaggered_classes.each do |swaggered_class|
|
44
|
+
next if !swaggered_class.respond_to?(:_swagger_nodes, true)
|
45
|
+
swagger_nodes = swaggered_class.send(:_swagger_nodes)
|
46
|
+
root_node = swagger_nodes[:resource_listing_node]
|
47
|
+
root_nodes << root_node if root_node
|
48
|
+
api_node_map.merge!(swagger_nodes[:api_node_map])
|
49
|
+
models_nodes << swagger_nodes[:models_node] if swagger_nodes[:models_node]
|
50
|
+
end
|
51
|
+
root_node = self.get_resource_listing(root_nodes)
|
52
|
+
|
53
|
+
{
|
54
|
+
root_node: root_node,
|
55
|
+
api_node_map: api_node_map,
|
56
|
+
models_nodes: models_nodes,
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# Make sure there is exactly one root_node and return it.
|
61
|
+
def self.get_resource_listing(root_nodes)
|
62
|
+
if root_nodes.length == 0
|
63
|
+
raise Swagger::Blocks::DeclarationError.new(
|
64
|
+
'swagger_root must be declared')
|
65
|
+
elsif root_nodes.length > 1
|
66
|
+
raise Swagger::Blocks::DeclarationError.new(
|
67
|
+
'Only one swagger_root declaration is allowed.')
|
68
|
+
end
|
69
|
+
root_nodes.first
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
private
|
75
|
+
|
76
|
+
# Defines a Swagger Resource Listing.
|
77
|
+
# http://goo.gl/PvwUXj#51-resource-listing
|
78
|
+
def swagger_root(&block)
|
79
|
+
@swagger_root_node ||= Swagger::Blocks::ResourceListingNode.call(&block)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Defines a Swagger API Declaration.
|
83
|
+
# http://goo.gl/PvwUXj#52-api-declaration
|
84
|
+
#
|
85
|
+
# @param resource_name [Symbol] An identifier for this API. All swagger_api_root declarations
|
86
|
+
# with the same resource_name will be merged into a single API root node.
|
87
|
+
def swagger_api_root(resource_name, &block)
|
88
|
+
resource_name = resource_name.to_sym
|
89
|
+
|
90
|
+
# Map of path names to ApiDeclarationNodes.
|
91
|
+
@swagger_api_root_node_map ||= {}
|
92
|
+
|
93
|
+
# Grab a previously declared node if it exists, otherwise create a new ApiDeclarationNode.
|
94
|
+
# This merges all declarations of swagger_api_root with the same resource_name key.
|
95
|
+
api_node = @swagger_api_root_node_map[resource_name]
|
96
|
+
if api_node
|
97
|
+
# Merge this swagger_api_root declaration into the previous one by the same resource_name.
|
98
|
+
api_node.instance_eval(&block)
|
99
|
+
else
|
100
|
+
# First time we've seen this `swagger_api_root :resource_name`.
|
101
|
+
api_node = Swagger::Blocks::ApiDeclarationNode.call(&block)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Add it into the resource_name to node map (may harmlessly overwrite the same object).
|
105
|
+
@swagger_api_root_node_map[resource_name] = api_node
|
106
|
+
end
|
107
|
+
|
108
|
+
# Defines a Swagger Model.
|
109
|
+
# http://goo.gl/PvwUXj#526-models-object
|
110
|
+
def swagger_model(name, &block)
|
111
|
+
@swagger_models_node ||= Swagger::Blocks::ModelsNode.new
|
112
|
+
@swagger_models_node.model(name, &block)
|
113
|
+
end
|
114
|
+
|
115
|
+
def _swagger_nodes
|
116
|
+
@swagger_root_node ||= nil # Avoid initialization warnings.
|
117
|
+
@swagger_api_root_node_map ||= {}
|
118
|
+
@swagger_models_node ||= nil
|
119
|
+
{
|
120
|
+
resource_listing_node: @swagger_root_node,
|
121
|
+
api_node_map: @swagger_api_root_node_map,
|
122
|
+
models_node: @swagger_models_node,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# -----
|
128
|
+
|
129
|
+
# Base node for representing every object in the Swagger DSL.
|
130
|
+
class Node
|
131
|
+
attr_accessor :name
|
132
|
+
|
133
|
+
def self.call(name: nil, &block)
|
134
|
+
# Create a new instance and evaluate the block into it.
|
135
|
+
instance = new
|
136
|
+
instance.name = name if name # Set the first parameter given as the name.
|
137
|
+
instance.instance_eval(&block)
|
138
|
+
instance
|
139
|
+
end
|
140
|
+
|
141
|
+
def as_json
|
142
|
+
result = {}
|
143
|
+
self.data.each do |key, value|
|
144
|
+
if value.is_a?(Node)
|
145
|
+
result[key] = value.as_json
|
146
|
+
elsif value.is_a?(Array)
|
147
|
+
result[key] = []
|
148
|
+
value.each { |v| result[key] << (v.respond_to?(:as_json) ? v.as_json : v) }
|
149
|
+
else
|
150
|
+
result[key] = value
|
151
|
+
end
|
152
|
+
end
|
153
|
+
return result if !name
|
154
|
+
# If "name" is given to this node, wrap the data with a root element with the given name.
|
155
|
+
{name => result}
|
156
|
+
end
|
157
|
+
|
158
|
+
def data
|
159
|
+
@data ||= {}
|
160
|
+
end
|
161
|
+
|
162
|
+
def key(key, value)
|
163
|
+
self.data[key] = value
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# -----
|
168
|
+
# Nodes for the Resource Listing.
|
169
|
+
# -----
|
170
|
+
|
171
|
+
# http://goo.gl/PvwUXj#51-resource-listing
|
172
|
+
class ResourceListingNode < Node
|
173
|
+
def initialize(*args)
|
174
|
+
# An internal list of the user-defined names that uniquely identify each API tree.
|
175
|
+
@api_paths = []
|
176
|
+
super
|
177
|
+
end
|
178
|
+
|
179
|
+
def has_api_path?(api_path)
|
180
|
+
api_paths = self.data[:apis].map { |x| x.data[:path] }
|
181
|
+
api_paths.include?(api_path)
|
182
|
+
end
|
183
|
+
|
184
|
+
def info(&block)
|
185
|
+
self.data[:info] = InfoNode.call(&block)
|
186
|
+
end
|
187
|
+
|
188
|
+
def authorization(name, &block)
|
189
|
+
self.data[:authorizations] ||= Swagger::Blocks::ResourceListingAuthorizationsNode.new
|
190
|
+
self.data[:authorizations].authorization(name, &block)
|
191
|
+
end
|
192
|
+
|
193
|
+
def api(&block)
|
194
|
+
self.data[:apis] ||= []
|
195
|
+
self.data[:apis] << Swagger::Blocks::ResourceNode.call(&block)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# http://goo.gl/PvwUXj#512-resource-object
|
200
|
+
class ResourceNode < Node; end
|
201
|
+
|
202
|
+
# NOTE: in the spec this is different than API Declaration authorizations.
|
203
|
+
# http://goo.gl/PvwUXj#514-authorizations-object
|
204
|
+
class ResourceListingAuthorizationsNode < Node
|
205
|
+
def authorization(name, &block)
|
206
|
+
self.data[name] = Swagger::Blocks::ResourceListingAuthorizationNode.call(&block)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# NOTE: in the spec this is different than API Declaration authorization.
|
211
|
+
# http://goo.gl/PvwUXj#515-authorization-object
|
212
|
+
class ResourceListingAuthorizationNode < Node
|
213
|
+
GRANT_TYPES = [:implicit, :authorization_code].freeze
|
214
|
+
|
215
|
+
def scope(&block)
|
216
|
+
self.data[:scopes] ||= []
|
217
|
+
self.data[:scopes] << Swagger::Blocks::ScopeNode.call(&block)
|
218
|
+
end
|
219
|
+
|
220
|
+
def grant_type(name, &block)
|
221
|
+
raise ArgumentError.new("#{name} not in #{GRANT_TYPES}") if !GRANT_TYPES.include?(name)
|
222
|
+
self.data[:grantTypes] ||= Swagger::Blocks::GrantTypesNode.new
|
223
|
+
self.data[:grantTypes].implicit(&block) if name == :implicit
|
224
|
+
self.data[:grantTypes].authorization_code(&block) if name == :authorization_code
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# http://goo.gl/PvwUXj#513-info-object
|
229
|
+
class InfoNode < Node; end
|
230
|
+
|
231
|
+
# http://goo.gl/PvwUXj#516-scope-object
|
232
|
+
class ScopeNode < Node; end
|
233
|
+
|
234
|
+
# http://goo.gl/PvwUXj#517-grant-types-object
|
235
|
+
class GrantTypesNode < Node
|
236
|
+
def implicit(&block)
|
237
|
+
self.data[:implicit] = Swagger::Blocks::ImplicitNode.call(&block)
|
238
|
+
end
|
239
|
+
|
240
|
+
def authorization_code(&block)
|
241
|
+
self.data[:authorization_code] = Swagger::Blocks::AuthorizationCodeNode.call(&block)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# http://goo.gl/PvwUXj#518-implicit-object
|
246
|
+
class ImplicitNode < Node
|
247
|
+
def login_endpoint(&block)
|
248
|
+
self.data[:loginEndpoint] = Swagger::Blocks::LoginEndpointNode.call(&block)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# http://goo.gl/PvwUXj#5110-login-endpoint-object
|
253
|
+
class LoginEndpointNode < Node; end
|
254
|
+
|
255
|
+
# http://goo.gl/PvwUXj#519-authorization-code-object
|
256
|
+
class AuthorizationCodeNode < Node
|
257
|
+
def token_request_endpoint(&block)
|
258
|
+
self.data[:tokenRequestEndpoint] = Swagger::Blocks::TokenRequestEndpointNode.call(&block)
|
259
|
+
end
|
260
|
+
|
261
|
+
def token_endpoint(&block)
|
262
|
+
self.data[:tokenEndpoint] = Swagger::Blocks::TokenEndpointNode.call(&block)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# http://goo.gl/PvwUXj#5111-token-request-endpoint-object
|
267
|
+
class TokenRequestEndpointNode < Node; end
|
268
|
+
|
269
|
+
# http://goo.gl/PvwUXj#5112-token-endpoint-object
|
270
|
+
class TokenEndpointNode < Node; end
|
271
|
+
|
272
|
+
# -----
|
273
|
+
# Nodes for API Declarations.
|
274
|
+
# -----
|
275
|
+
|
276
|
+
# http://goo.gl/PvwUXj#52-api-declaration
|
277
|
+
class ApiDeclarationNode < Node
|
278
|
+
def api(&block)
|
279
|
+
self.data[:apis] ||= []
|
280
|
+
|
281
|
+
# Important: to conform with the Swagger spec, merge with any previous API declarations
|
282
|
+
# that have the same :path key. This ensures that operations affecting the same resource
|
283
|
+
# are all in the same operations node.
|
284
|
+
#
|
285
|
+
# http://goo.gl/PvwUXj#522-api-object
|
286
|
+
# - The API Object describes one or more operations on a single path. In the apis array,
|
287
|
+
# there MUST be only one API Object per path.
|
288
|
+
temp_api_node = Swagger::Blocks::ApiNode.call(&block)
|
289
|
+
api_node = self.data[:apis].select do |api|
|
290
|
+
api.data[:path] == temp_api_node.data[:path]
|
291
|
+
end[0] # Embrace Ruby wtfs.
|
292
|
+
|
293
|
+
if api_node
|
294
|
+
# Merge this block with the previous ApiNode by the same path key.
|
295
|
+
api_node.instance_eval(&block)
|
296
|
+
else
|
297
|
+
# First time we've seen an api block with the given path key.
|
298
|
+
self.data[:apis] << temp_api_node
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# http://goo.gl/PvwUXj#522-api-object
|
304
|
+
class ApiNode < Node
|
305
|
+
def operation(&block)
|
306
|
+
self.data[:operations] ||= []
|
307
|
+
self.data[:operations] << Swagger::Blocks::OperationNode.call(&block)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
class OperationNode < Node
|
312
|
+
def parameter(&block)
|
313
|
+
self.data[:parameters] ||= []
|
314
|
+
self.data[:parameters] << Swagger::Blocks::ParameterNode.call(&block)
|
315
|
+
end
|
316
|
+
|
317
|
+
def response_message(&block)
|
318
|
+
self.data[:responseMessages] ||= []
|
319
|
+
self.data[:responseMessages] << Swagger::Blocks::Node.call(&block)
|
320
|
+
end
|
321
|
+
|
322
|
+
def authorization(name, &block)
|
323
|
+
self.data[:authorizations] ||= Swagger::Blocks::ApiAuthorizationsNode.new
|
324
|
+
self.data[:authorizations].authorization(name, &block)
|
325
|
+
end
|
326
|
+
|
327
|
+
def items(&block)
|
328
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(&block)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# NOTE: in the spec this is different than Resource Listing's authorizations.
|
333
|
+
# http://goo.gl/PvwUXj#514-authorizations-object
|
334
|
+
class ApiAuthorizationsNode < Node
|
335
|
+
def authorization(name, &block)
|
336
|
+
self.data[name] ||= Swagger::Blocks::ApiAuthorizationNode.call(&block)
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
# NOTE: in the spec this is different than Resource Listing's authorization.
|
341
|
+
# http://goo.gl/PvwUXj#515-authorization-object
|
342
|
+
class ApiAuthorizationNode < Node
|
343
|
+
def as_json
|
344
|
+
# Special case: the API Authorization object is weirdly the only array of hashes.
|
345
|
+
# Override the default hash behavior and return an array.
|
346
|
+
self.data[:_scopes] ||= []
|
347
|
+
self.data[:_scopes].map { |s| s.as_json }
|
348
|
+
end
|
349
|
+
|
350
|
+
def scope(&block)
|
351
|
+
self.data[:_scopes] ||= []
|
352
|
+
self.data[:_scopes] << Swagger::Blocks::ApiAuthorizationScopeNode.call(&block)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
# NOTE: in the spec this is different than Resource Listing's scope object.
|
357
|
+
# http://goo.gl/PvwUXj#5211-scope-object
|
358
|
+
class ApiAuthorizationScopeNode < Node; end
|
359
|
+
|
360
|
+
# http://goo.gl/PvwUXj#434-items-object
|
361
|
+
class ItemsNode < Node; end
|
362
|
+
|
363
|
+
# http://goo.gl/PvwUXj#524-parameter-object
|
364
|
+
class ParameterNode < Node; end
|
365
|
+
|
366
|
+
# -----
|
367
|
+
# Nodes for Models.
|
368
|
+
# -----
|
369
|
+
|
370
|
+
# http://goo.gl/PvwUXj#526-models-object
|
371
|
+
class ModelsNode < Node
|
372
|
+
def merge!(other_models_node)
|
373
|
+
self.data.merge!(other_models_node.data)
|
374
|
+
end
|
375
|
+
|
376
|
+
def model(name, &block)
|
377
|
+
self.data[name] ||= Swagger::Blocks::ModelNode.call(&block)
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
# http://goo.gl/PvwUXj#527-model-object
|
382
|
+
class ModelNode < Node
|
383
|
+
def property(name, &block)
|
384
|
+
self.data[:properties] ||= Swagger::Blocks::PropertiesNode.new
|
385
|
+
self.data[:properties].property(name, &block)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
# http://goo.gl/PvwUXj#527-model-object
|
390
|
+
class PropertiesNode < Node
|
391
|
+
def property(name, &block)
|
392
|
+
self.data[name] = Swagger::Blocks::PropertyNode.call(&block)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
# http://goo.gl/PvwUXj#527-model-object
|
397
|
+
class PropertyNode < Node
|
398
|
+
def items(&block)
|
399
|
+
self.data[:items] = Swagger::Blocks::ItemsNode.call(&block)
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
{
|
2
|
+
"apiVersion": "1.0.0",
|
3
|
+
"swaggerVersion": "1.2",
|
4
|
+
"basePath": "http://petstore.swagger.wordnik.com/api",
|
5
|
+
"resourcePath": "/pet",
|
6
|
+
"produces": [
|
7
|
+
"application/json",
|
8
|
+
"application/xml",
|
9
|
+
"text/plain",
|
10
|
+
"text/html"
|
11
|
+
],
|
12
|
+
"apis": [
|
13
|
+
{
|
14
|
+
"path": "/pet/{petId}",
|
15
|
+
"operations": [
|
16
|
+
{
|
17
|
+
"method": "GET",
|
18
|
+
"summary": "Find pet by ID",
|
19
|
+
"notes": "Returns a pet based on ID",
|
20
|
+
"type": "Pet",
|
21
|
+
"nickname": "getPetById",
|
22
|
+
"parameters": [
|
23
|
+
{
|
24
|
+
"name": "petId",
|
25
|
+
"description": "ID of pet that needs to be fetched",
|
26
|
+
"required": true,
|
27
|
+
"type": "integer",
|
28
|
+
"format": "int64",
|
29
|
+
"paramType": "path",
|
30
|
+
"minimum": "1.0",
|
31
|
+
"maximum": "100000.0"
|
32
|
+
}
|
33
|
+
],
|
34
|
+
"responseMessages": [
|
35
|
+
{
|
36
|
+
"code": 400,
|
37
|
+
"message": "Invalid ID supplied"
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"code": 404,
|
41
|
+
"message": "Pet not found"
|
42
|
+
}
|
43
|
+
]
|
44
|
+
},
|
45
|
+
{
|
46
|
+
"method": "PATCH",
|
47
|
+
"summary": "partial updates to a pet",
|
48
|
+
"notes": "",
|
49
|
+
"type": "array",
|
50
|
+
"items": {
|
51
|
+
"$ref": "Pet"
|
52
|
+
},
|
53
|
+
"nickname": "partialUpdate",
|
54
|
+
"produces": [
|
55
|
+
"application/json",
|
56
|
+
"application/xml"
|
57
|
+
],
|
58
|
+
"consumes": [
|
59
|
+
"application/json",
|
60
|
+
"application/xml"
|
61
|
+
],
|
62
|
+
"authorizations": {
|
63
|
+
"oauth2": [
|
64
|
+
{
|
65
|
+
"scope": "test:anything",
|
66
|
+
"description": "anything"
|
67
|
+
}
|
68
|
+
]
|
69
|
+
},
|
70
|
+
"parameters": [
|
71
|
+
{
|
72
|
+
"name": "petId",
|
73
|
+
"description": "ID of pet that needs to be fetched",
|
74
|
+
"required": true,
|
75
|
+
"type": "string",
|
76
|
+
"paramType": "path"
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"name": "body",
|
80
|
+
"description": "Pet object that needs to be added to the store",
|
81
|
+
"required": true,
|
82
|
+
"type": "Pet",
|
83
|
+
"paramType": "body"
|
84
|
+
}
|
85
|
+
],
|
86
|
+
"responseMessages": [
|
87
|
+
{
|
88
|
+
"code": 400,
|
89
|
+
"message": "Invalid tag value"
|
90
|
+
}
|
91
|
+
]
|
92
|
+
}
|
93
|
+
]
|
94
|
+
},
|
95
|
+
{
|
96
|
+
"path": "/pet/findByStatus",
|
97
|
+
"operations": [
|
98
|
+
{
|
99
|
+
"method": "GET",
|
100
|
+
"summary": "Finds Pets by status",
|
101
|
+
"notes": "Multiple status values can be provided with comma seperated strings",
|
102
|
+
"type": "array",
|
103
|
+
"items": {
|
104
|
+
"$ref": "Pet"
|
105
|
+
},
|
106
|
+
"nickname": "findPetsByStatus",
|
107
|
+
"parameters": [
|
108
|
+
{
|
109
|
+
"name": "status",
|
110
|
+
"description": "Status values that need to be considered for filter",
|
111
|
+
"defaultValue": "available",
|
112
|
+
"required": true,
|
113
|
+
"type": "string",
|
114
|
+
"paramType": "query",
|
115
|
+
"enum": [
|
116
|
+
"available",
|
117
|
+
"pending",
|
118
|
+
"sold"
|
119
|
+
]
|
120
|
+
}
|
121
|
+
],
|
122
|
+
"responseMessages": [
|
123
|
+
{
|
124
|
+
"code": 400,
|
125
|
+
"message": "Invalid status value"
|
126
|
+
}
|
127
|
+
]
|
128
|
+
}
|
129
|
+
]
|
130
|
+
}
|
131
|
+
],
|
132
|
+
"models": {
|
133
|
+
"Tag": {
|
134
|
+
"id": "Tag",
|
135
|
+
"properties": {
|
136
|
+
"id": {
|
137
|
+
"type": "integer",
|
138
|
+
"format": "int64"
|
139
|
+
},
|
140
|
+
"name": {
|
141
|
+
"type": "string"
|
142
|
+
}
|
143
|
+
}
|
144
|
+
},
|
145
|
+
"Pet": {
|
146
|
+
"id": "Pet",
|
147
|
+
"required": [
|
148
|
+
"id",
|
149
|
+
"name"
|
150
|
+
],
|
151
|
+
"properties": {
|
152
|
+
"id": {
|
153
|
+
"type": "integer",
|
154
|
+
"format": "int64",
|
155
|
+
"description": "unique identifier for the pet",
|
156
|
+
"minimum": "0.0",
|
157
|
+
"maximum": "100.0"
|
158
|
+
},
|
159
|
+
"category": {
|
160
|
+
"$ref": "Category"
|
161
|
+
},
|
162
|
+
"name": {
|
163
|
+
"type": "string"
|
164
|
+
},
|
165
|
+
"photoUrls": {
|
166
|
+
"type": "array",
|
167
|
+
"items": {
|
168
|
+
"type": "string"
|
169
|
+
}
|
170
|
+
},
|
171
|
+
"tags": {
|
172
|
+
"type": "array",
|
173
|
+
"items": {
|
174
|
+
"$ref": "Tag"
|
175
|
+
}
|
176
|
+
},
|
177
|
+
"status": {
|
178
|
+
"type": "string",
|
179
|
+
"description": "pet status in the store",
|
180
|
+
"enum": [
|
181
|
+
"available",
|
182
|
+
"pending",
|
183
|
+
"sold"
|
184
|
+
]
|
185
|
+
}
|
186
|
+
}
|
187
|
+
},
|
188
|
+
"Category": {
|
189
|
+
"id": "Category",
|
190
|
+
"properties": {
|
191
|
+
"id": {
|
192
|
+
"type": "integer",
|
193
|
+
"format": "int64"
|
194
|
+
},
|
195
|
+
"name": {
|
196
|
+
"type": "string"
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}
|
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'swagger/blocks'
|
3
|
+
|
4
|
+
# Test data originally based on the Swagger UI example data:
|
5
|
+
# https://github.com/wordnik/swagger-codegen/blob/master/src/test/resources/petstore-1.2/api-docs
|
6
|
+
RESOURCE_LISTING_JSON = open(File.expand_path('../swagger_resource_listing.json', __FILE__)).read
|
7
|
+
# https://github.com/wordnik/swagger-codegen/blob/master/src/test/resources/petstore-1.2/pet
|
8
|
+
API_DECLARATION_JSON = open(File.expand_path('../swagger_api_declaration.json', __FILE__)).read
|
9
|
+
|
10
|
+
class PetController
|
11
|
+
include Swagger::Blocks
|
12
|
+
|
13
|
+
swagger_root do
|
14
|
+
key :swaggerVersion, '1.2'
|
15
|
+
key :apiVersion, '1.0.0'
|
16
|
+
info do
|
17
|
+
key :title, 'Swagger Sample App'
|
18
|
+
key :description, "This is a sample server Petstore server. You can find out more about Swagger \n at <a href=\"http://swagger.wordnik.com\">http://swagger.wordnik.com</a> or on irc.freenode.net, #swagger. For this sample,\n you can use the api key \"special-key\" to test the authorization filters"
|
19
|
+
key :termsOfServiceUrl, 'http://helloreverb.com/terms/'
|
20
|
+
key :contact, 'apiteam@wordnik.com'
|
21
|
+
key :license, 'Apache 2.0'
|
22
|
+
key :licenseUrl, 'http://www.apache.org/licenses/LICENSE-2.0.html'
|
23
|
+
end
|
24
|
+
api do
|
25
|
+
key :path, '/pet'
|
26
|
+
key :description, 'Operations about pets'
|
27
|
+
end
|
28
|
+
api do
|
29
|
+
key :path, '/user'
|
30
|
+
key :description, 'Operations about user'
|
31
|
+
end
|
32
|
+
api do
|
33
|
+
key :path, '/store'
|
34
|
+
key :description, 'Operations about store'
|
35
|
+
end
|
36
|
+
authorization :oauth2 do
|
37
|
+
key :type, 'oauth2'
|
38
|
+
scope do
|
39
|
+
key :scope, 'email'
|
40
|
+
key :description, 'Access to your email address'
|
41
|
+
end
|
42
|
+
scope do
|
43
|
+
key :scope, 'pets'
|
44
|
+
key :description, 'Access to your pets'
|
45
|
+
end
|
46
|
+
grant_type :implicit do
|
47
|
+
login_endpoint do
|
48
|
+
key :url, 'http://petstore.swagger.wordnik.com/oauth/dialog'
|
49
|
+
end
|
50
|
+
key :tokenName, 'access_token'
|
51
|
+
end
|
52
|
+
grant_type :authorization_code do
|
53
|
+
token_request_endpoint do
|
54
|
+
key :url, 'http://petstore.swagger.wordnik.com/oauth/requestToken'
|
55
|
+
key :clientIdName, 'client_id'
|
56
|
+
key :clientSecretName, 'client_secret'
|
57
|
+
end
|
58
|
+
token_endpoint do
|
59
|
+
key :url, 'http://petstore.swagger.wordnik.com/oauth/token'
|
60
|
+
key :tokenName, 'access_code'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# All swagger_api_root declarations with the same key will be merged.
|
67
|
+
swagger_api_root :pets do
|
68
|
+
key :swaggerVersion, '1.2'
|
69
|
+
key :apiVersion, '1.0.0'
|
70
|
+
key :basePath, 'http://petstore.swagger.wordnik.com/api'
|
71
|
+
key :resourcePath, '/pet'
|
72
|
+
key :produces, [
|
73
|
+
'application/json',
|
74
|
+
'application/xml',
|
75
|
+
'text/plain',
|
76
|
+
'text/html',
|
77
|
+
]
|
78
|
+
api do
|
79
|
+
key :path, '/pet/{petId}'
|
80
|
+
operation do
|
81
|
+
key :method, 'GET'
|
82
|
+
key :summary, 'Find pet by ID'
|
83
|
+
key :notes, 'Returns a pet based on ID'
|
84
|
+
key :type, :Pet
|
85
|
+
key :nickname, :getPetById
|
86
|
+
parameter do
|
87
|
+
key :paramType, :path
|
88
|
+
key :name, :petId
|
89
|
+
key :description, 'ID of pet that needs to be fetched'
|
90
|
+
key :required, true
|
91
|
+
key :type, :integer
|
92
|
+
key :format, :int64
|
93
|
+
key :minimum, '1.0'
|
94
|
+
key :maximum, '100000.0'
|
95
|
+
end
|
96
|
+
response_message do
|
97
|
+
key :code, 400
|
98
|
+
key :message, 'Invalid ID supplied'
|
99
|
+
end
|
100
|
+
response_message do
|
101
|
+
key :code, 404
|
102
|
+
key :message, 'Pet not found'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
swagger_api_root :pets do
|
109
|
+
api do
|
110
|
+
key :path, '/pet/{petId}'
|
111
|
+
operation do
|
112
|
+
key :method, 'PATCH'
|
113
|
+
key :summary, 'partial updates to a pet'
|
114
|
+
key :notes, ''
|
115
|
+
key :type, :array
|
116
|
+
key :nickname, :partialUpdate
|
117
|
+
items do
|
118
|
+
key :'$ref', :Pet
|
119
|
+
end
|
120
|
+
key :produces, [
|
121
|
+
'application/json',
|
122
|
+
'application/xml',
|
123
|
+
]
|
124
|
+
key :consumes, [
|
125
|
+
'application/json',
|
126
|
+
'application/xml',
|
127
|
+
]
|
128
|
+
authorization :oauth2 do
|
129
|
+
scope do
|
130
|
+
key :scope, 'test:anything'
|
131
|
+
key :description, 'anything'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
parameter do
|
135
|
+
key :paramType, :path
|
136
|
+
key :name, :petId
|
137
|
+
key :description, 'ID of pet that needs to be fetched'
|
138
|
+
key :required, true
|
139
|
+
key :type, :string
|
140
|
+
end
|
141
|
+
parameter do
|
142
|
+
key :paramType, :body
|
143
|
+
key :name, :body
|
144
|
+
key :description, 'Pet object that needs to be added to the store'
|
145
|
+
key :required, true
|
146
|
+
key :type, :Pet
|
147
|
+
end
|
148
|
+
response_message do
|
149
|
+
key :code, 400
|
150
|
+
key :message, 'Invalid tag value'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
swagger_api_root :pets do
|
157
|
+
api do
|
158
|
+
key :path, '/pet/findByStatus'
|
159
|
+
operation do
|
160
|
+
key :method, 'GET'
|
161
|
+
key :summary, 'Finds Pets by status'
|
162
|
+
key :notes, 'Multiple status values can be provided with comma seperated strings'
|
163
|
+
key :type, :array
|
164
|
+
key :nickname, :findPetsByStatus
|
165
|
+
items do
|
166
|
+
key :'$ref', :Pet
|
167
|
+
end
|
168
|
+
parameter do
|
169
|
+
key :paramType, :query
|
170
|
+
key :name, :status
|
171
|
+
key :description, 'Status values that need to be considered for filter'
|
172
|
+
key :defaultValue, 'available'
|
173
|
+
key :required, true
|
174
|
+
key :type, :string
|
175
|
+
key :enum, [
|
176
|
+
'available',
|
177
|
+
'pending',
|
178
|
+
'sold',
|
179
|
+
]
|
180
|
+
end
|
181
|
+
response_message do
|
182
|
+
key :code, 400
|
183
|
+
key :message, 'Invalid status value'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
class StoreController
|
192
|
+
include Swagger::Blocks
|
193
|
+
|
194
|
+
swagger_api_root :stores do
|
195
|
+
key :path, '/store'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
class UserController
|
201
|
+
include Swagger::Blocks
|
202
|
+
|
203
|
+
swagger_api_root :users do
|
204
|
+
key :path, '/user'
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
class TagModel
|
210
|
+
include Swagger::Blocks
|
211
|
+
|
212
|
+
swagger_model :Tag do
|
213
|
+
key :id, :Tag
|
214
|
+
property :id do
|
215
|
+
key :type, :integer
|
216
|
+
key :format, :int64
|
217
|
+
end
|
218
|
+
property :name do
|
219
|
+
key :type, :string
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
class OtherModelsContainer
|
226
|
+
include Swagger::Blocks
|
227
|
+
|
228
|
+
swagger_model :Pet do
|
229
|
+
key :id, :Pet
|
230
|
+
key :required, [:id, :name]
|
231
|
+
property :id do
|
232
|
+
key :type, :integer
|
233
|
+
key :format, :int64
|
234
|
+
key :description, 'unique identifier for the pet'
|
235
|
+
key :minimum, '0.0'
|
236
|
+
key :maximum, '100.0'
|
237
|
+
end
|
238
|
+
property :category do
|
239
|
+
key :'$ref', :Category
|
240
|
+
end
|
241
|
+
property :name do
|
242
|
+
key :type, :string
|
243
|
+
end
|
244
|
+
property :photoUrls do
|
245
|
+
key :type, :array
|
246
|
+
items do
|
247
|
+
key :type, :string
|
248
|
+
end
|
249
|
+
end
|
250
|
+
property :tags do
|
251
|
+
key :type, :array
|
252
|
+
items do
|
253
|
+
key :'$ref', :Tag
|
254
|
+
end
|
255
|
+
end
|
256
|
+
property :status do
|
257
|
+
key :type, :string
|
258
|
+
key :description, 'pet status in the store'
|
259
|
+
key :enum, [:available, :pending, :sold]
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
swagger_model :Category do
|
264
|
+
key :id, :Category
|
265
|
+
property :id do
|
266
|
+
key :type, :integer
|
267
|
+
key :format, :int64
|
268
|
+
end
|
269
|
+
property :name do
|
270
|
+
key :type, :string
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
class BlankController; end
|
277
|
+
|
278
|
+
|
279
|
+
describe Swagger::Blocks do
|
280
|
+
describe 'build_root_json' do
|
281
|
+
it 'outputs the correct data' do
|
282
|
+
swaggered_classes = [
|
283
|
+
PetController,
|
284
|
+
UserController,
|
285
|
+
StoreController,
|
286
|
+
TagModel,
|
287
|
+
OtherModelsContainer,
|
288
|
+
]
|
289
|
+
actual = Swagger::Blocks.build_root_json(swaggered_classes)
|
290
|
+
|
291
|
+
# Multiple expectations for better test diff output.
|
292
|
+
actual = JSON.parse(actual.to_json) # For access consistency.
|
293
|
+
data = JSON.parse(RESOURCE_LISTING_JSON)
|
294
|
+
expect(actual['info']).to eq(data['info'])
|
295
|
+
expect(actual['authorizations']).to eq(data['authorizations'])
|
296
|
+
actual['apis'].each_with_index do |api_data, i|
|
297
|
+
expect(api_data).to eq(data['apis'][i])
|
298
|
+
end
|
299
|
+
expect(actual).to eq(data)
|
300
|
+
end
|
301
|
+
it 'is idempotent' do
|
302
|
+
swaggered_classes = [PetController, UserController, StoreController]
|
303
|
+
actual = JSON.parse(Swagger::Blocks.build_root_json(swaggered_classes).to_json)
|
304
|
+
actual = JSON.parse(Swagger::Blocks.build_root_json(swaggered_classes).to_json)
|
305
|
+
data = JSON.parse(RESOURCE_LISTING_JSON)
|
306
|
+
expect(actual).to eq(data)
|
307
|
+
end
|
308
|
+
it 'errors if no swagger_root is declared' do
|
309
|
+
expect {
|
310
|
+
Swagger::Blocks.build_root_json([])
|
311
|
+
}.to raise_error(Swagger::Blocks::DeclarationError)
|
312
|
+
end
|
313
|
+
it 'errors if mulitple swagger_roots are declared' do
|
314
|
+
expect {
|
315
|
+
Swagger::Blocks.build_root_json([PetController, PetController])
|
316
|
+
}.to raise_error(Swagger::Blocks::DeclarationError)
|
317
|
+
end
|
318
|
+
it 'does not error if given non-swaggered classes' do
|
319
|
+
Swagger::Blocks.build_root_json([PetController, BlankController])
|
320
|
+
end
|
321
|
+
end
|
322
|
+
describe 'build_api_json' do
|
323
|
+
it 'outputs the correct data' do
|
324
|
+
swaggered_classes = [
|
325
|
+
PetController,
|
326
|
+
UserController,
|
327
|
+
StoreController,
|
328
|
+
TagModel,
|
329
|
+
OtherModelsContainer,
|
330
|
+
]
|
331
|
+
actual = Swagger::Blocks.build_api_json(:pets, swaggered_classes)
|
332
|
+
|
333
|
+
# Multiple expectations for better test diff output.
|
334
|
+
actual = JSON.parse(actual.to_json) # For access consistency.
|
335
|
+
data = JSON.parse(API_DECLARATION_JSON)
|
336
|
+
expect(actual['apis'][0]).to be
|
337
|
+
expect(actual['apis'][0]['operations']).to be
|
338
|
+
expect(actual['apis'][0]['operations'][0]).to be
|
339
|
+
expect(actual['apis'][0]['operations'][1]).to be
|
340
|
+
expect(actual['apis'][0]['operations'][0]).to eq(data['apis'][0]['operations'][0])
|
341
|
+
expect(actual['apis'][0]['operations'][1]).to eq(data['apis'][0]['operations'][1])
|
342
|
+
expect(actual['apis'][0]['operations']).to eq(data['apis'][0]['operations'])
|
343
|
+
expect(actual['apis']).to eq(data['apis'])
|
344
|
+
expect(actual['models']).to eq(data['models'])
|
345
|
+
expect(actual).to eq(data)
|
346
|
+
end
|
347
|
+
it 'is idempotent' do
|
348
|
+
swaggered_classes = [
|
349
|
+
PetController,
|
350
|
+
UserController,
|
351
|
+
StoreController,
|
352
|
+
TagModel,
|
353
|
+
OtherModelsContainer,
|
354
|
+
]
|
355
|
+
actual = JSON.parse(Swagger::Blocks.build_api_json(:pets, swaggered_classes).to_json)
|
356
|
+
actual = JSON.parse(Swagger::Blocks.build_api_json(:pets, swaggered_classes).to_json)
|
357
|
+
data = JSON.parse(API_DECLARATION_JSON)
|
358
|
+
expect(actual).to eq(data)
|
359
|
+
end
|
360
|
+
it 'errors if no swagger_root is declared' do
|
361
|
+
expect {
|
362
|
+
Swagger::Blocks.build_root_json([])
|
363
|
+
}.to raise_error(Swagger::Blocks::DeclarationError)
|
364
|
+
end
|
365
|
+
it 'errors if mulitple swagger_roots are declared' do
|
366
|
+
expect {
|
367
|
+
Swagger::Blocks.build_root_json([PetController, PetController])
|
368
|
+
}.to raise_error(Swagger::Blocks::DeclarationError)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
{
|
2
|
+
"apiVersion": "1.0.0",
|
3
|
+
"swaggerVersion": "1.2",
|
4
|
+
"apis": [
|
5
|
+
{
|
6
|
+
"path": "/pet",
|
7
|
+
"description": "Operations about pets"
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"path": "/user",
|
11
|
+
"description": "Operations about user"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"path": "/store",
|
15
|
+
"description": "Operations about store"
|
16
|
+
}
|
17
|
+
],
|
18
|
+
"authorizations": {
|
19
|
+
"oauth2": {
|
20
|
+
"type": "oauth2",
|
21
|
+
"scopes": [
|
22
|
+
{
|
23
|
+
"scope": "email",
|
24
|
+
"description": "Access to your email address"
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"scope": "pets",
|
28
|
+
"description": "Access to your pets"
|
29
|
+
}
|
30
|
+
],
|
31
|
+
"grantTypes": {
|
32
|
+
"implicit": {
|
33
|
+
"loginEndpoint": {
|
34
|
+
"url": "http://petstore.swagger.wordnik.com/oauth/dialog"
|
35
|
+
},
|
36
|
+
"tokenName": "access_token"
|
37
|
+
},
|
38
|
+
"authorization_code": {
|
39
|
+
"tokenRequestEndpoint": {
|
40
|
+
"url": "http://petstore.swagger.wordnik.com/oauth/requestToken",
|
41
|
+
"clientIdName": "client_id",
|
42
|
+
"clientSecretName": "client_secret"
|
43
|
+
},
|
44
|
+
"tokenEndpoint": {
|
45
|
+
"url": "http://petstore.swagger.wordnik.com/oauth/token",
|
46
|
+
"tokenName": "access_code"
|
47
|
+
}
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
},
|
52
|
+
"info": {
|
53
|
+
"title": "Swagger Sample App",
|
54
|
+
"description": "This is a sample server Petstore server. You can find out more about Swagger \n at <a href=\"http://swagger.wordnik.com\">http://swagger.wordnik.com</a> or on irc.freenode.net, #swagger. For this sample,\n you can use the api key \"special-key\" to test the authorization filters",
|
55
|
+
"termsOfServiceUrl": "http://helloreverb.com/terms/",
|
56
|
+
"contact": "apiteam@wordnik.com",
|
57
|
+
"license": "Apache 2.0",
|
58
|
+
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
59
|
+
}
|
60
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
2
|
+
RSpec.configure do |config|
|
3
|
+
# Allow more verbose output when running an individual spec file.
|
4
|
+
if config.files_to_run.one?
|
5
|
+
config.default_formatter = 'doc'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Run specs in random order to surface order dependencies. If you find an
|
9
|
+
# order dependency and want to debug it, you can fix the order by providing
|
10
|
+
# the seed, which is printed after each run.
|
11
|
+
# --seed 1234
|
12
|
+
config.order = :random
|
13
|
+
|
14
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
15
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
16
|
+
# test failures related to randomization by passing the same `--seed` value
|
17
|
+
# as the one that triggered the failure.
|
18
|
+
Kernel.srand config.seed
|
19
|
+
|
20
|
+
# rspec-expectations config goes here. You can use an alternate
|
21
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
22
|
+
# assertions if you prefer.
|
23
|
+
config.expect_with :rspec do |expectations|
|
24
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
25
|
+
# For more details, see:
|
26
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
27
|
+
expectations.syntax = :expect
|
28
|
+
end
|
29
|
+
|
30
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
31
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
32
|
+
config.mock_with :rspec do |mocks|
|
33
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
34
|
+
# For more details, see:
|
35
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
36
|
+
mocks.syntax = :expect
|
37
|
+
|
38
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
39
|
+
# a real object. This is generally recommended.
|
40
|
+
mocks.verify_partial_doubles = true
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'swagger/blocks/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'swagger-blocks'
|
8
|
+
spec.version = Swagger::Blocks::VERSION
|
9
|
+
spec.authors = ['Mike Fotinakis']
|
10
|
+
spec.email = ['mike@fotinakis.com']
|
11
|
+
spec.summary = %q{Define and generate Swagger JSON files in Ruby.}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = 'https://github.com/fotinakis/swagger-blocks'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swagger-blocks
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Fotinakis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ''
|
70
|
+
email:
|
71
|
+
- mike@fotinakis.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- lib/swagger/blocks.rb
|
84
|
+
- lib/swagger/blocks/version.rb
|
85
|
+
- spec/lib/swagger_api_declaration.json
|
86
|
+
- spec/lib/swagger_blocks_spec.rb
|
87
|
+
- spec/lib/swagger_resource_listing.json
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- swagger-blocks.gemspec
|
90
|
+
homepage: https://github.com/fotinakis/swagger-blocks
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.4.1
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: Define and generate Swagger JSON files in Ruby.
|
114
|
+
test_files:
|
115
|
+
- spec/lib/swagger_api_declaration.json
|
116
|
+
- spec/lib/swagger_blocks_spec.rb
|
117
|
+
- spec/lib/swagger_resource_listing.json
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
has_rdoc:
|