swagger-blocks 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/fotinakis/swagger-blocks.svg?branch=master)](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:
|