skeleton 0.3.3 → 0.4.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.
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