skeleton 0.3.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +140 -65
  4. data/Rakefile +10 -3
  5. data/lib/skeleton.rb +6 -10
  6. data/lib/skeleton/contact.rb +1 -13
  7. data/lib/skeleton/error.rb +4 -0
  8. data/lib/skeleton/graph.rb +56 -0
  9. data/lib/skeleton/header.rb +2 -63
  10. data/lib/skeleton/items.rb +34 -0
  11. data/lib/skeleton/license.rb +1 -12
  12. data/lib/skeleton/model.rb +13 -17
  13. data/lib/skeleton/operation.rb +50 -121
  14. data/lib/skeleton/parameter.rb +31 -88
  15. data/lib/skeleton/parameters.rb +40 -0
  16. data/lib/skeleton/path.rb +42 -80
  17. data/lib/skeleton/presenter.rb +19 -0
  18. data/lib/skeleton/property.rb +6 -0
  19. data/lib/skeleton/response.rb +24 -45
  20. data/lib/skeleton/schema.rb +80 -63
  21. data/lib/skeleton/scope.rb +18 -0
  22. data/lib/skeleton/security_scheme.rb +19 -37
  23. data/lib/skeleton/serializers/options.rb +215 -0
  24. data/lib/skeleton/serializers/swagger.rb +197 -0
  25. data/lib/skeleton/structure.rb +92 -138
  26. data/lib/skeleton/swagger.rb +9 -0
  27. data/lib/skeleton/tag.rb +11 -16
  28. data/lib/skeleton/version.rb +1 -1
  29. data/skeleton.gemspec +2 -0
  30. data/test/fixtures/json-schema-draft-04.json +150 -0
  31. data/test/fixtures/schema.json +1482 -0
  32. data/test/integrations/validate_complex_schema_spec.rb +42 -0
  33. data/test/skeleton/graph_test.rb +22 -0
  34. data/test/skeleton/mapper_test.rb +84 -0
  35. data/test/skeleton/operation_test.rb +11 -0
  36. data/test/skeleton/parameter_test.rb +34 -0
  37. data/test/skeleton/parameters_test.rb +9 -0
  38. data/test/skeleton/path_test.rb +46 -0
  39. data/test/skeleton/property_test.rb +8 -0
  40. data/test/skeleton/serializers/options_test.rb +68 -0
  41. data/test/skeleton/serializers/swagger_test.rb +30 -0
  42. data/test/support/factories/structure_factory.rb +86 -0
  43. data/test/support/fixtures.rb +6 -0
  44. data/test/support/kissmetrics/core_api.rb +542 -0
  45. data/{spec/spec_helper.rb → test/test_helper.rb} +7 -1
  46. metadata +73 -25
  47. data/lib/skeleton/config.rb +0 -37
  48. data/lib/skeleton/documentation.rb +0 -17
  49. data/lib/skeleton/example.rb +0 -31
  50. data/lib/skeleton/headers.rb +0 -50
  51. data/lib/skeleton/helpers/controller_helpers.rb +0 -25
  52. data/lib/skeleton/info.rb +0 -40
  53. data/lib/skeleton/item.rb +0 -99
  54. data/lib/skeleton/responses.rb +0 -59
  55. data/lib/skeleton/scopes.rb +0 -24
  56. data/lib/skeleton/security_definitions.rb +0 -46
  57. data/lib/skeleton/security_requirement.rb +0 -29
  58. data/spec/integrations/use_case_spec.rb +0 -131
  59. data/spec/skeleton/operation_spec.rb +0 -113
  60. data/spec/skeleton/serializers/contact_spec.rb +0 -30
  61. data/spec/skeleton/serializers/documentation_spec.rb +0 -23
  62. data/spec/skeleton/serializers/header_spec.rb +0 -57
@@ -0,0 +1,18 @@
1
+ require 'skeleton/attributes'
2
+ module Skeleton
3
+ class Scope
4
+ extend Skeleton::Attributes
5
+
6
+ attr_accessor :name, :description
7
+ attr_presence :name, :description
8
+
9
+ def initialize(args={})
10
+ args.each do |k, v|
11
+ setter = "#{k}="
12
+ self.send(setter, v) if self.respond_to?(setter)
13
+ end
14
+ end
15
+
16
+ alias_method :describe, :description=
17
+ end
18
+ end
@@ -1,47 +1,29 @@
1
- require 'skeleton/model'
2
- require 'skeleton/scopes'
1
+ require 'skeleton/attributes'
2
+ require 'skeleton/scope'
3
3
 
4
4
  module Skeleton
5
- class SecurityScheme < Model
6
- attr_accessor :type, :description, :name, :location, :flow, :authorization_url,
7
- :token_url, :scopes
5
+ class SecurityScheme
6
+ extend Skeleton::Attributes
8
7
 
9
- attr_presence :type, :description, :name, :location, :flow, :authorization_url,
10
- :token_url, :scopes
8
+ attr_accessor :type, :description, :name, :location, :flow,
9
+ :authorization_url, :token_url
11
10
 
12
- def scopes=(value)
13
- case value
14
- when Hash
15
- @scopes = Skeleton::Scopes.new(value)
16
- else
17
- @scopes = value
18
- end
19
- end
11
+ attr_presence :type, :description, :name, :location, :flow,
12
+ :authorization_url, :token_url
20
13
 
21
- def to_h
22
- hash = {}
23
- hash[:type] = type if type?
24
- hash[:description] = description if description?
25
- hash[:name] = name if name?
26
- hash[:location] = location if location?
27
- hash[:flow] = flow if flow?
28
- hash[:authorization_url] = authorization_url if authorization_url?
29
- hash[:token_url] = token_url if token_url?
30
- hash[:scopes] = scopes.to_h if scopes?
31
- hash
14
+ def initialize(args={})
15
+ @scopes = {}
16
+
17
+ args.each do |k, v|
18
+ setter = "#{k}="
19
+ self.send(setter, v) if self.respond_to?(setter)
20
+ end
32
21
  end
33
22
 
34
- def to_swagger_hash
35
- hash = {}
36
- hash[:type] = type if type?
37
- hash[:description] = description if description?
38
- hash[:name] = name if name?
39
- hash[:location] = location if location?
40
- hash[:flow] = flow if flow?
41
- hash[:authorizationUrl] = authorization_url if authorization_url?
42
- hash[:tokenUrl] = token_url if token_url?
43
- hash[:scopes] = scopes.to_swagger_hash if scopes?
44
- hash
23
+ def define_scope(name, &block)
24
+ @scopes[name] = Skeleton::Scope.new
25
+ @scopes[name].instance_eval(&block)
26
+ @scopes[name]
45
27
  end
46
28
  end
47
29
  end
@@ -0,0 +1,215 @@
1
+ require 'multi_json'
2
+ require 'skeleton/error'
3
+ require 'skeleton/graph'
4
+
5
+ module Skeleton
6
+ module Serializers
7
+ class Options
8
+ attr_reader :structure
9
+
10
+ def initialize(structure, options={})
11
+ @structure = structure
12
+
13
+ @path = options[:path] || raise(Skeleton::Error, ':path is required')
14
+ @definition_path = options[:definitions] || '#/definitions'
15
+
16
+ end
17
+
18
+ def to_json(*)
19
+ MultiJson.dump(to_h)
20
+ end
21
+
22
+ def to_h
23
+ graph = Skeleton::Graph.new
24
+ structure.models.each do |name, model|
25
+ graph.register(name, dependencies_for(model))
26
+ end
27
+
28
+ hash = {
29
+ consumes: structure.consumes.map(&:to_s),
30
+ produces: structure.produces.map(&:to_s)
31
+ }
32
+
33
+ if structure.parameters?
34
+ hash[:parameters] = {}
35
+ structure.parameters.each do |name, parameter|
36
+ hash[:parameters][name] = parameter_to_h(parameter)
37
+ end
38
+ end
39
+
40
+ if structure.responses?
41
+ hash[:responses] = {}
42
+ structure.responses.each do |name, response|
43
+ hash[:responses][name] = response_to_h(response)
44
+ end
45
+ end
46
+
47
+ if structure.secure?
48
+ hash[:security_definitions] = {},
49
+ hash[:security] = []
50
+ end
51
+
52
+ hash[:tags] = structure.tags.map do |name, tag|
53
+ sub = {
54
+ name: name
55
+ }
56
+ sub[:description] = tag.description if tag.description?
57
+ sub[:external_docs] = tag.external_docs if tag.external_docs?
58
+ sub
59
+ end
60
+
61
+ path = structure.paths.fetch(@path) { raise(Skeleton::Error, "path '#{@path}' not found in structure") }
62
+ hash[:operations] ||= {}
63
+ path.operations.each do |verb, operation|
64
+ hash[:operations][verb] = operation_to_h(operation)
65
+ end
66
+
67
+ hash[:definitions] ||= {}
68
+
69
+ dependencies.to_a.each do |dep|
70
+ graph.each_dependent_for(dep) do |name|
71
+ hash[:definitions][name] = schema_to_h(structure.models[name])
72
+ end
73
+ end
74
+
75
+ hash
76
+ end
77
+
78
+ def dependencies
79
+ @definitions ||= Set.new
80
+ end
81
+
82
+ def register_dependent(name)
83
+ dependencies.add(name)
84
+ end
85
+
86
+ def dependencies_for(schema, set=Set.new)
87
+ return set if schema.nil?
88
+
89
+ if schema.ref?
90
+ return set if set.include?(schema.ref)
91
+ set.add(schema.ref)
92
+ end
93
+
94
+ schema.properties.each do |field, property|
95
+ set.merge(dependencies_for(property))
96
+ end
97
+
98
+ set.merge(dependencies_for(schema.items)) if schema.items?
99
+
100
+ set.to_a
101
+ end
102
+
103
+ def definition_reference(name)
104
+ '%s/%s' % [@definition_path, name]
105
+ end
106
+
107
+ def parameter_to_h(parameter)
108
+ hash = {
109
+ name: parameter.name,
110
+ in: parameter.location,
111
+ required: parameter.required?
112
+ }.merge(schema_to_h(parameter))
113
+
114
+ hash[:schema] = schema_to_h(parameter.schema) if parameter.schema?
115
+ hash
116
+ end
117
+
118
+ def items_to_h(items)
119
+ return nil if items.nil?
120
+ hash = {
121
+ type: items.type
122
+ }
123
+ hash[:format] = items.format if items.format?
124
+ if items.array?
125
+ hash[:items] = items_to_h(items)
126
+ hash[:collectionFormat] = items.collection_format
127
+ end
128
+ hash.merge(schema_to_h(items))
129
+ hash
130
+ end
131
+
132
+ def schema_to_h(schema)
133
+ hash = {}
134
+
135
+ return hash if schema.nil?
136
+
137
+ if schema.ref?
138
+ hash['$ref'] = definition_reference(schema.ref)
139
+ dependencies.merge(dependencies_for(schema))
140
+ dependencies.add(schema.ref)
141
+ end
142
+
143
+ hash[:description] = schema.description if schema.description?
144
+ hash[:default] = schema.default if schema.default?
145
+ hash[:maximum] = schema.maximum if schema.maximum?
146
+ hash[:exclusive_maximum] = !!schema.exclusive_maximum if schema.exclusive_maximum?
147
+ hash[:minimum] = schema.minimum if schema.minimum?
148
+ hash[:exclusive_minimum] = !!schema.exclusive_minimum if schema.exclusive_minimum?
149
+ hash[:max_length] = schema.max_length if schema.max_length?
150
+ hash[:min_length] = schema.min_length if schema.min_length?
151
+ hash[:pattern] = schema.pattern if schema.pattern?
152
+ hash[:max_items] = schema.max_items if schema.max_items?
153
+ hash[:min_items] = schema.min_items if schema.min_items?
154
+ hash[:unique_items] = !!schema.unique_items if schema.unique_items?
155
+ hash[:enum] = schema.enum.map(&:to_s) unless schema.enum.empty?
156
+ hash[:multiple_of] = schema.multiple_of if schema.multiple_of?
157
+ hash[:type] = schema.type if schema.type
158
+
159
+ if schema.properties?
160
+ hash[:properties] = {}
161
+ schema.properties.each do |name, prop|
162
+ hash[:properties][name] = schema_to_h(prop)
163
+ end
164
+ end
165
+
166
+ if schema.items?
167
+ hash[:items] = schema_to_h(schema.items)
168
+ end
169
+ hash
170
+ end
171
+
172
+ def response_to_h(response)
173
+ hash = {
174
+ description: response.description
175
+ }
176
+ if response.schema?
177
+ hash[:schema] = schema_to_h(response.schema)
178
+ end
179
+
180
+ hash[:headers] = {}
181
+ response.headers.each do |field, header|
182
+ hash[:headers][field] = schema_to_h(header)
183
+ end
184
+ hash
185
+ end
186
+
187
+ def operation_to_h(operation)
188
+ hash = {
189
+ tags: operation.tags,
190
+ summary: operation.summary,
191
+ description: operation.description,
192
+ responses: {}
193
+ }
194
+
195
+ hash[:deprecated] = true if operation.deprecated?
196
+ hash[:operation_id] = operation.id if operation.id?
197
+ hash[:consumes] = operation.consumes if operation.consumes?
198
+ hash[:produces] = operation.produces if operation.produces?
199
+
200
+ operation.responses.each do |status, response|
201
+ hash[:responses][status] = response_to_h(response)
202
+ end
203
+
204
+ if operation.parameters?
205
+ hash[:parameters] = operation.parameters.map do |parameter|
206
+ parameter_to_h(parameter)
207
+ end
208
+ end
209
+
210
+ hash
211
+ end
212
+
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,197 @@
1
+ require 'multi_json'
2
+
3
+ module Skeleton
4
+ module Serializers
5
+ class Swagger
6
+ attr_reader :structure
7
+
8
+ def initialize(structure)
9
+ @structure = structure
10
+ end
11
+
12
+ def to_json(*)
13
+ MultiJson.dump(to_h)
14
+ end
15
+
16
+ def to_h
17
+ hash = {
18
+ swagger: '2.0',
19
+ info: {
20
+ title: structure.title,
21
+ description: structure.description,
22
+ version: structure.version,
23
+ termsOfService: structure.terms,
24
+ contact: {
25
+ name: structure.contact.name,
26
+ email: structure.contact.email,
27
+ url: structure.contact.url
28
+ },
29
+ license: {
30
+ name: structure.license.name,
31
+ url: structure.license.url
32
+ }
33
+ },
34
+ basePath: structure.base_path,
35
+ host: structure.host,
36
+ schemes: structure.schemes.map(&:to_s),
37
+ consumes: structure.consumes.map(&:to_s),
38
+ produces: structure.produces.map(&:to_s)
39
+ }
40
+
41
+ if structure.parameters?
42
+ hash[:parameters] = {}
43
+ structure.parameters.each do |name, parameter|
44
+ hash[:parameters][name] = parameter_to_h(parameter)
45
+ end
46
+ end
47
+
48
+ if structure.responses?
49
+ hash[:responses] = {}
50
+ structure.responses.each do |name, response|
51
+ hash[:responses][name] = response_to_h(response)
52
+ end
53
+ end
54
+
55
+ if structure.secure?
56
+ hash[:securityDefinitions] = {},
57
+ hash[:security] = []
58
+ end
59
+
60
+ hash[:tags] = structure.tags.map do |name, tag|
61
+ sub = {
62
+ name: name
63
+ }
64
+ sub[:description] = tag.description if tag.description?
65
+ sub[:externalDocs] = tag.external_docs if tag.external_docs?
66
+ sub
67
+ end
68
+
69
+ if structure.external_docs
70
+ hash[:externalDocs] = structure.external_docs
71
+ end
72
+
73
+ hash[:paths] = {}
74
+ structure.paths.each do |resource, path|
75
+ hash[:paths][resource] = {}
76
+
77
+ path.operations.each do |verb, operation|
78
+ hash[:paths][resource][verb] = operation_to_h(operation)
79
+ end
80
+ end
81
+
82
+ hash[:definitions] = {}
83
+ structure.models.each do |name, model|
84
+ hash[:definitions][name] = schema_to_h(model)
85
+ end
86
+
87
+ hash
88
+ end
89
+
90
+ private
91
+
92
+ def definition_ref(name)
93
+ '#/definitions/%s' % [name]
94
+ end
95
+
96
+ def parameter_to_h(parameter)
97
+ hash = {
98
+ name: parameter.name,
99
+ in: parameter.location,
100
+ required: parameter.required?
101
+ }.merge(schema_to_h(parameter))
102
+ hash[:schema] = schema_to_h(parameter.schema) if parameter.schema?
103
+ hash
104
+ end
105
+
106
+ def items_to_h(items)
107
+ return nil if items.nil?
108
+ hash = {
109
+ type: items.type
110
+ }
111
+ hash[:format] = items.format if items.format?
112
+ if items.array?
113
+ hash[:items] = items_to_h(items)
114
+ hash[:collectionFormat] = items.collection_format
115
+ end
116
+ hash.merge(schema_to_h(items))
117
+ hash
118
+ end
119
+
120
+ def schema_to_h(schema)
121
+ hash = {}
122
+ return hash if schema.nil?
123
+
124
+ hash['$ref'] = definition_ref(schema.ref) if schema.ref?
125
+ hash[:description] = schema.description if schema.description?
126
+ hash[:default] = schema.default if schema.default?
127
+ hash[:maximum] = schema.maximum if schema.maximum?
128
+ hash[:exclusiveMaximum] = !!schema.exclusive_maximum if schema.exclusive_maximum?
129
+ hash[:minimum] = schema.minimum if schema.minimum?
130
+ hash[:exclusiveMinimum] = !!schema.exclusive_minimum if schema.exclusive_minimum?
131
+ hash[:maxLength] = schema.max_length if schema.max_length?
132
+ hash[:minLength] = schema.min_length if schema.min_length?
133
+ hash[:pattern] = schema.pattern if schema.pattern?
134
+ hash[:maxItems] = schema.max_items if schema.max_items?
135
+ hash[:minItems] = schema.min_items if schema.min_items?
136
+ hash[:uniqueItems] = !!schema.unique_items if schema.unique_items?
137
+ hash[:enum] = schema.enum.map(&:to_s) unless schema.enum.empty?
138
+ hash[:multipleOf] = schema.multiple_of if schema.multiple_of?
139
+ hash[:type] = schema.type if schema.type
140
+
141
+ if schema.properties?
142
+ hash[:properties] = {}
143
+ schema.properties.each do |name, prop|
144
+ hash[:properties][name] = schema_to_h(prop)
145
+ end
146
+ end
147
+
148
+ if schema.items?
149
+ hash[:items] = schema_to_h(schema.items)
150
+ end
151
+ hash
152
+ end
153
+
154
+ def response_to_h(response)
155
+ hash = {
156
+ description: response.description
157
+ }
158
+ if response.schema?
159
+ hash[:schema] = schema_to_h(response.schema)
160
+ end
161
+
162
+ hash[:headers] = {}
163
+ response.headers.each do |field, header|
164
+ hash[:headers][field] = schema_to_h(header)
165
+ end
166
+ hash
167
+ end
168
+
169
+ def operation_to_h(operation)
170
+ hash = {
171
+ tags: operation.tags,
172
+ summary: operation.summary,
173
+ description: operation.description,
174
+ responses: {}
175
+ }
176
+
177
+ hash[:deprecated] = true if operation.deprecated?
178
+ hash[:operationId] = operation.id if operation.id?
179
+ hash[:consumes] = operation.consumes if operation.consumes?
180
+ hash[:produces] = operation.produces if operation.produces?
181
+
182
+ operation.responses.each do |status, response|
183
+ hash[:responses][status] = response_to_h(response)
184
+ end
185
+
186
+ if operation.parameters?
187
+ hash[:parameters] = operation.parameters.map do |parameter|
188
+ parameter_to_h(parameter)
189
+ end
190
+ end
191
+
192
+ hash
193
+ end
194
+
195
+ end
196
+ end
197
+ end