raml_parser 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +39 -0
  8. data/Rakefile +7 -0
  9. data/lib/raml_parser.rb +270 -0
  10. data/lib/raml_parser/model.rb +146 -0
  11. data/lib/raml_parser/version.rb +3 -0
  12. data/lib/raml_parser/yaml_helper.rb +122 -0
  13. data/raml_parser.gemspec +26 -0
  14. data/spec/examples/raml/documentation.raml +11 -0
  15. data/spec/examples/raml/external/box.raml +8473 -0
  16. data/spec/examples/raml/external/bug.raml +12 -0
  17. data/spec/examples/raml/external/github.raml +21650 -0
  18. data/spec/examples/raml/external/groups_and_nesting.raml +22 -0
  19. data/spec/examples/raml/external/instagram.yml +3369 -0
  20. data/spec/examples/raml/external/json_schema.json +18 -0
  21. data/spec/examples/raml/external/jukebox-api.raml +191 -0
  22. data/spec/examples/raml/external/jukebox-include-album-new.sample +8 -0
  23. data/spec/examples/raml/external/jukebox-include-album-retrieve.sample +30 -0
  24. data/spec/examples/raml/external/jukebox-include-album-songs.sample +14 -0
  25. data/spec/examples/raml/external/jukebox-include-album.schema +36 -0
  26. data/spec/examples/raml/external/jukebox-include-albums.sample +32 -0
  27. data/spec/examples/raml/external/jukebox-include-artist-albums.sample +42 -0
  28. data/spec/examples/raml/external/jukebox-include-artist-new.sample +5 -0
  29. data/spec/examples/raml/external/jukebox-include-artist-retrieve.sample +52 -0
  30. data/spec/examples/raml/external/jukebox-include-artist.schema +20 -0
  31. data/spec/examples/raml/external/jukebox-include-artists.sample +32 -0
  32. data/spec/examples/raml/external/jukebox-include-song-new.sample +5 -0
  33. data/spec/examples/raml/external/jukebox-include-song-retrieve.sample +15 -0
  34. data/spec/examples/raml/external/jukebox-include-song.schema +24 -0
  35. data/spec/examples/raml/external/jukebox-include-songs.sample +14 -0
  36. data/spec/examples/raml/external/linkedin-v1-single.yml +2671 -0
  37. data/spec/examples/raml/external/mule_sales_enablement.raml +148 -0
  38. data/spec/examples/raml/external/multiple-methods.raml +11 -0
  39. data/spec/examples/raml/external/named_parameters.raml +85 -0
  40. data/spec/examples/raml/external/requests-responses.raml +47 -0
  41. data/spec/examples/raml/external/resource_summary_spacing.raml +42 -0
  42. data/spec/examples/raml/external/simple.raml +233 -0
  43. data/spec/examples/raml/external/stripe.raml +12226 -0
  44. data/spec/examples/raml/external/test.raml +11 -0
  45. data/spec/examples/raml/external/twitter.raml +34284 -0
  46. data/spec/examples/raml/external/xml_example.xml +25 -0
  47. data/spec/examples/raml/external/xml_schema.xsd +50 -0
  48. data/spec/examples/raml/formparameters.raml +23 -0
  49. data/spec/examples/raml/headers.raml +15 -0
  50. data/spec/examples/raml/issue2.raml +51 -0
  51. data/spec/examples/raml/methods.raml +9 -0
  52. data/spec/examples/raml/parameters.raml +21 -0
  53. data/spec/examples/raml/parametersinflection.raml +21 -0
  54. data/spec/examples/raml/queryparameters.raml +14 -0
  55. data/spec/examples/raml/requestbodies.raml +21 -0
  56. data/spec/examples/raml/resources.raml +15 -0
  57. data/spec/examples/raml/resourcetypes.raml +16 -0
  58. data/spec/examples/raml/responses.raml +25 -0
  59. data/spec/examples/raml/securedby1.raml +20 -0
  60. data/spec/examples/raml/securedby2.raml +21 -0
  61. data/spec/examples/raml/securityschemes.raml +47 -0
  62. data/spec/examples/raml/simple.raml +6 -0
  63. data/spec/examples/raml/traits.raml +34 -0
  64. data/spec/examples/raml/uriparameters.raml +16 -0
  65. data/spec/examples/yaml/include1.yml +2 -0
  66. data/spec/examples/yaml/include2.yml +1 -0
  67. data/spec/examples/yaml/simple.yml +2 -0
  68. data/spec/examples/yaml/traversing.yml +11 -0
  69. data/spec/lib/raml_parser/yaml_parser_spec.rb +38 -0
  70. data/spec/lib/raml_parser_spec.rb +196 -0
  71. data/spec/spec_helper.rb +91 -0
  72. metadata +229 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 15632f30b43baa8f09f37bb3f06b10fee158f138
4
+ data.tar.gz: 87d3a333ef6dbb848da083db0f344e9e0041a404
5
+ SHA512:
6
+ metadata.gz: 251ac847b813be9b1bea013ded667d10208d377b56f75edae87bce4fe5a352ca3f8d94f3fea44297c9527ce6b227521ad4eeded792eadcf2b96acb8c2d2b770a
7
+ data.tar.gz: 6fbf700a78e581c13ebf1248621fe7c280215580651f8096c974ee80f9b0e3fbff78fa4feb61bc8017879c3d2a1ce8ef8eb8c5ba567cd623dfa127175efdf0c1
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in my_ruby_gem.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Christian Hoffmeister
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,39 @@
1
+ # RamlParser
2
+
3
+ [![build](https://img.shields.io/travis/ePages-de/raml_parser/develop.svg)](https://travis-ci.org/ePages-de/raml_parser)
4
+ [![license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT)
5
+
6
+ A parser for the [RAML](http://raml.org/) API modeling language.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'raml_parser', :git => 'https://github.com/ePages-de/raml_parser.git', :branch => 'master'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ ## Usage
21
+
22
+ TODO: Write usage instructions here
23
+
24
+ ## What parts of RAML are not supported
25
+
26
+ These are features of the RAML 0.8 specification that are not fully handled yet. This list should be complete, i.e. everything not listed here should work.
27
+
28
+ * [Base URI Parameters](http://raml.org/spec.html#base-uri-parameters)
29
+ * [Schemas](http://raml.org/spec.html#schemas)
30
+ * [Protocols](http://raml.org/spec.html#protocols)
31
+ * [Named parameters with multiple types](http://raml.org/spec.html#named-parameters-with-multiple-types)
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/ePages-de/raml_parser/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ multitask :default => [:test]
4
+ task :spec => :test
5
+
6
+ require "rspec/core/rake_task"
7
+ RSpec::Core::RakeTask.new(:test)
@@ -0,0 +1,270 @@
1
+ require 'raml_parser/yaml_helper'
2
+ require 'raml_parser/model'
3
+
4
+ module RamlParser
5
+ class Parser
6
+ attr_reader :path, :root
7
+
8
+ def self.parse_file(path)
9
+ node = YamlNode.new(nil, 'root', YamlHelper.read_yaml(path))
10
+ parse_root(node)
11
+ end
12
+
13
+ def self.parse_file_with_marks(path)
14
+ node = YamlNode.new(nil, 'root', YamlHelper.read_yaml(path))
15
+ node.mark_all(:unused)
16
+ node.mark(:used)
17
+ root = parse_root(node)
18
+ { :root => root, :marks => node.marks }
19
+ end
20
+
21
+ private
22
+
23
+ def self.parse_root(node)
24
+ node.hash('schemas').mark_all(:unsupported) if node.value.has_key? 'schemas'
25
+
26
+ root = Model::Root.new
27
+ root.title = node.hash('title').or_default('').value
28
+ root.base_uri = node.hash('baseUri').or_default('').value
29
+ root.version = node.hash('version').value
30
+ root.media_type = node.hash('mediaType').value
31
+ root.secured_by = node.hash('securedBy').or_default([]).array_map { |n| n.value }
32
+ root.documentation = node.hash('documentation').array_map { |n| parse_documenation(n) }
33
+ root.security_schemes = node.hash('securitySchemes').arrayhash_map { |n| parse_security_scheme(n) }
34
+ root.resource_types = node.hash('resourceTypes').mark_all(:used).arrayhash_map { |n| n }
35
+ root.traits = node.hash('traits').mark_all(:used).arrayhash_map { |n| n }
36
+
37
+ root.resources = traverse_resources(node, nil) do |n,parent|
38
+ parent_absolute_uri = parent != nil ? parent.absolute_uri : root.base_uri || ''
39
+ parent_relative_uri = parent != nil ? parent.relative_uri : ''
40
+ parent_uri_parameters = parent != nil ? parent.uri_parameters.clone : {}
41
+ parse_resource(n, root, parent_absolute_uri, parent_relative_uri, parent_uri_parameters, false)
42
+ end
43
+
44
+ root
45
+ end
46
+
47
+ def self.parse_resource(node, root, parent_absolute_uri, parent_relative_uri, parent_uri_parameters, as_resource_type)
48
+ def self.extract_uri_parameters(relative_uri)
49
+ names = relative_uri.scan(/\{([a-zA-Z\_\-]+)\}/).map { |m| m.first }
50
+ Hash[names.map { |name| [name, Model::NamedParameter.new(name, 'string', name)] }]
51
+ end
52
+
53
+ node = node.or_default({})
54
+ resource = Model::Resource.new(parent_absolute_uri + node.key, parent_relative_uri + node.key)
55
+ resource.display_name = node.hash('displayName').value
56
+ resource.description = node.hash('description').value
57
+ resource.uri_parameters = extract_uri_parameters(node.key).merge(parent_uri_parameters.merge(node.hash('uriParameters').hash_map { |n| parse_named_parameter(n) }))
58
+ resource.type = parse_type(node.hash('type'))
59
+ resource.is = parse_is(node.hash('is'))
60
+ resource.secured_by = (root.secured_by + node.hash('securedBy').or_default([]).array_map { |n| n.value }).uniq
61
+
62
+ for m in %w(get post put delete head patch options trace connect) do
63
+ if node.value.has_key? m
64
+ resource.methods[m] = parse_method(node.hash(m), root, resource, as_resource_type)
65
+ end
66
+ end
67
+
68
+ unless as_resource_type
69
+ resource = mixin_resource_types(node, root, resource)
70
+ resource.display_name = resource.relative_uri unless resource.display_name
71
+ end
72
+
73
+ resource
74
+ end
75
+
76
+ def self.parse_method(node, root, resource, as_trait)
77
+ node = node.or_default({})
78
+ method = Model::Method.new(node.key.upcase)
79
+ method.display_name = node.hash('displayName').value
80
+ method.description = node.hash('description').value
81
+ method.query_parameters = node.hash('queryParameters').hash_map { |n| parse_named_parameter(n) }
82
+ method.bodies = node.hash('body').hash_map { |n| parse_body(n) }
83
+ method.responses = node.hash('responses').hash_map { |n| parse_response(n) }
84
+ method.headers = node.hash('headers').hash_map { |n| parse_named_parameter(n) }
85
+ method.secured_by = (resource.secured_by + node.hash('securedBy').or_default([]).array_map { |n| n.value }).uniq if resource
86
+ method.is = parse_is(node.hash('is'))
87
+
88
+ unless as_trait
89
+ method = mixin_traits(node, root, method, resource)
90
+ method.display_name = method.method + ' ' + resource.relative_uri unless method.display_name
91
+ end
92
+
93
+ method
94
+ end
95
+
96
+ def self.parse_response(node)
97
+ node = node.or_default({})
98
+ response = Model::Response.new(node.key)
99
+ response.display_name = node.hash('displayName').value
100
+ response.description = node.hash('description').value
101
+ response.bodies = node.hash('body').hash_map { |n| parse_body(n) }
102
+ response.headers = node.hash('headers').hash_map { |n| parse_named_parameter(n) }
103
+ response
104
+ end
105
+
106
+ def self.parse_named_parameter(node)
107
+ if node.value.is_a? Array
108
+ node.mark_all(:unsupported)
109
+ # TODO: Not yet supported named parameters with multiple types
110
+ return Model::NamedParameter.new(node.key)
111
+ end
112
+
113
+ node = node.or_default({})
114
+ named_parameter = Model::NamedParameter.new(node.key)
115
+ named_parameter.type = node.hash('type').or_default('string').value
116
+ named_parameter.display_name = node.hash('displayName').or_default(named_parameter.name).value
117
+ named_parameter.description = node.hash('description').value
118
+ named_parameter.required = node.hash('required').or_default(true).value
119
+ named_parameter.default = node.hash('default').value
120
+ named_parameter.example = node.hash('example').value
121
+ named_parameter.min_length = node.hash('minLength').value
122
+ named_parameter.max_length = node.hash('maxLength').value
123
+ named_parameter.minimum = node.hash('minimum').value
124
+ named_parameter.maximum = node.hash('maximum').value
125
+ named_parameter.repeat = node.hash('repeat').value
126
+ named_parameter.enum = node.hash('enum').or_default([]).array_map { |n| n.value }
127
+ named_parameter.pattern = node.hash('pattern').value
128
+ named_parameter
129
+ end
130
+
131
+ def self.parse_body(node)
132
+ node = node.or_default({})
133
+ body = Model::Body.new(node.key)
134
+ body.example = node.hash('example').value
135
+ body.schema = node.hash('schema').value
136
+ body.form_parameters = node.hash('formParameters').hash_map { |n| parse_named_parameter(n) }
137
+ # TODO: Form parameters are only allowed for media type application/x-www-form-urlencoded or multipart/form-data
138
+ body
139
+ end
140
+
141
+ def self.parse_security_scheme(node)
142
+ node.hash('describedBy').mark_all(:unsupported) if node.value.has_key? 'describedBy'
143
+
144
+ node = node.or_default({})
145
+ security_scheme = Model::SecurityScheme.new(node.key)
146
+ security_scheme.type = node.hash('type').value
147
+ security_scheme.description = node.hash('description').value
148
+ security_scheme.described_by = node.hash('describedBy').value
149
+ security_scheme.settings = node.hash('settings').mark_all(:used).value
150
+ security_scheme
151
+ end
152
+
153
+ def self.parse_documenation(node)
154
+ node = node.or_default({})
155
+ documentation = Model::Documentation.new
156
+ documentation.title = node.hash('title').value
157
+ documentation.content = node.hash('content').value
158
+ documentation
159
+ end
160
+
161
+ def self.parse_type(node)
162
+ node = node.or_default({}).mark_all(:used)
163
+ result = {}
164
+ if node.value.is_a? String
165
+ result = { node.value => nil }
166
+ elsif node.value.is_a? Hash
167
+ result = node.value
168
+ else
169
+ raise "Invalid syntax for 'type' property at #{node.path}"
170
+ end
171
+ result
172
+ end
173
+
174
+ def self.parse_is(node)
175
+ node = node.or_default({}).mark_all(:used)
176
+ result = {}
177
+ node.value.each { |n|
178
+ if n.is_a? String
179
+ result = result.merge({ n => nil })
180
+ elsif n.is_a? Hash
181
+ result = result.merge(n)
182
+ else
183
+ raise "Invalid syntax for 'is' property at #{node.path}"
184
+ end
185
+ }
186
+ result
187
+ end
188
+
189
+ def self.mixin_resource_types(node, root, resource)
190
+ result = Model::Resource.new(nil, nil)
191
+ resource.type.each do |name,value|
192
+ params = (value || {}).merge({
193
+ 'resourcePath' => resource.relative_uri,
194
+ 'resourcePathName' => resource.relative_uri.match(/[^\/]*$/).to_s
195
+ })
196
+ resource_type = root.resource_types.has_key?(name) ? parse_resource(resolve_parametrization(root.resource_types[name], params), root, '', '', {}, true) : nil
197
+ if resource_type != nil
198
+ result = Model::Resource.merge(result, resource_type)
199
+ else
200
+ raise "Referencing unknown resource type #{name} at #{node.path}"
201
+ end
202
+ end
203
+
204
+ Model::Resource.merge(result, resource)
205
+ end
206
+
207
+ def self.mixin_traits(node, root, method, resource)
208
+ result = Model::Method.new(nil)
209
+ (resource.is.merge(method.is)).each do |name,value|
210
+ params = (value || {}).merge({
211
+ 'resourcePath' => resource.relative_uri,
212
+ 'resourcePathName' => resource.relative_uri.match(/[^\/]*$/).to_s,
213
+ 'methodName' => method.method.downcase
214
+ })
215
+ trait = root.traits.has_key?(name) ? parse_method(resolve_parametrization(root.traits[name], params), root, nil, true) : nil
216
+ if trait != nil
217
+ result = Model::Method.merge(result, trait)
218
+ else
219
+ raise "Referencing unknown trait #{name} at #{node.path}"
220
+ end
221
+ end
222
+
223
+ Model::Method.merge(result, method)
224
+ end
225
+
226
+ def self.resolve_parametrization(node, params)
227
+ require 'active_support/core_ext/string/inflections'
228
+
229
+ def self.alter_string(str, params, node)
230
+ str.gsub(/<<([a-zA-Z]+)(\s*\|\s*!([a-zA-Z_\-]+))?>>/) do |a,b|
231
+ case $3
232
+ when nil
233
+ params[$1].to_s
234
+ when 'singularize'
235
+ params[$1].to_s.singularize
236
+ when 'pluralize'
237
+ params[$1].to_s.pluralize
238
+ else
239
+ raise "Using unknown parametrization function #{$3} at #{node.path}"
240
+ end
241
+ end
242
+ end
243
+
244
+ def self.traverse(raw, params, node)
245
+ if raw.is_a? Hash
246
+ Hash[raw.map { |k,v| [traverse(k, params, node), traverse(v, params, node)] }]
247
+ elsif raw.is_a? Array
248
+ raw.map { |i| traverse(i, params, node) }
249
+ elsif raw.is_a? String
250
+ alter_string(raw, params, node)
251
+ else
252
+ raw
253
+ end
254
+ end
255
+
256
+ YamlNode.new(node.parent, node.key, traverse(node.value, params, node))
257
+ end
258
+
259
+ def self.traverse_resources(node, parent_resource, &code)
260
+ node.hash_map { |n|
261
+ if n.key =~ /^\//
262
+ resource = code.call(n, parent_resource)
263
+ [resource] + traverse_resources(n, resource, &code)
264
+ else
265
+ []
266
+ end
267
+ }.values.flatten
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,146 @@
1
+ module RamlParser
2
+ module Model
3
+ class Root
4
+ attr_accessor :title, :base_uri, :version, :media_type, :security_schemes, :resource_types, :traits, :secured_by, :documentation, :resources
5
+
6
+ def initialize(title = nil, base_uri = nil, version = nil, media_type = nil, security_schemes = {}, resource_types = {}, traits = {}, secured_by = [], documentation = [], resources = [])
7
+ @title = title
8
+ @base_uri = base_uri
9
+ @version = version
10
+ @media_type = media_type
11
+ @security_schemes = security_schemes
12
+ @resource_types = resource_types
13
+ @traits = traits
14
+ @secured_by = secured_by
15
+ @documentation = documentation
16
+ @resources = resources
17
+ end
18
+ end
19
+
20
+ class Resource
21
+ attr_accessor :absolute_uri, :relative_uri, :display_name, :description, :uri_parameters, :methods, :type, :is, :secured_by
22
+
23
+ def initialize(absolute_uri, relative_uri, display_name = nil, description = nil, uri_parameters = {}, methods = {}, type = {}, is = {}, secured_by = [])
24
+ @absolute_uri = absolute_uri
25
+ @relative_uri = relative_uri
26
+ @display_name = display_name
27
+ @description = description
28
+ @uri_parameters = uri_parameters
29
+ @methods = methods
30
+ @type = type
31
+ @is = is
32
+ @secured_by = secured_by
33
+ end
34
+
35
+ def self.merge(a, b)
36
+ resource = Resource.new(b.absolute_uri, b.relative_uri)
37
+
38
+ resource.display_name = if b.display_name then b.display_name else a.display_name end
39
+ resource.description = if b.description then b.description else a.description end
40
+ resource.uri_parameters = a.uri_parameters.merge(b.uri_parameters)
41
+ resource.methods = a.methods.merge(b.methods)
42
+ resource.type = a.type.merge(b.type)
43
+ resource.is = a.is.merge(b.is)
44
+ resource.secured_by = (a.secured_by + b.secured_by).uniq
45
+
46
+ resource
47
+ end
48
+ end
49
+
50
+ class Method
51
+ attr_accessor :method, :display_name, :description, :query_parameters, :responses, :bodies, :headers, :is, :secured_by
52
+
53
+ def initialize(method, display_name = nil, description = nil, query_parameters = {}, responses = {}, bodies = {}, headers = {}, is = {}, secured_by = [])
54
+ @method = method
55
+ @display_name = display_name
56
+ @description = description
57
+ @query_parameters = query_parameters
58
+ @responses = responses
59
+ @bodies = bodies
60
+ @headers = headers
61
+ @is = is
62
+ @secured_by = secured_by
63
+ end
64
+
65
+ def self.merge(a, b)
66
+ method = Method.new(b.method)
67
+
68
+ method.display_name = if b.display_name then b.display_name else a.display_name end
69
+ method.description = if b.description then b.description else a.description end
70
+ method.query_parameters = a.query_parameters.merge(b.query_parameters)
71
+ method.responses = a.responses.merge(b.responses)
72
+ method.bodies = a.bodies.merge(b.bodies)
73
+ method.headers = a.headers.merge(b.headers)
74
+ method.is = a.is.merge(b.is)
75
+ method.secured_by = (a.secured_by + b.secured_by).uniq
76
+
77
+ method
78
+ end
79
+ end
80
+
81
+ class Response
82
+ attr_accessor :status_code, :display_name, :description, :bodies, :headers
83
+
84
+ def initialize(status_code, display_name = nil, description = nil, bodies = {}, headers = {})
85
+ @status_code = status_code
86
+ @display_name = display_name
87
+ @description = description
88
+ @bodies = bodies
89
+ @headers = headers
90
+ end
91
+ end
92
+
93
+ class Body
94
+ attr_accessor :media_type, :example, :schema, :form_parameters
95
+
96
+ def initialize(media_type, example = nil, schema = nil, form_parameters = {})
97
+ @media_type = media_type
98
+ @example = example
99
+ @schema = schema
100
+ @form_parameters = form_parameters
101
+ end
102
+ end
103
+
104
+ class NamedParameter
105
+ attr_accessor :name, :type, :display_name, :description, :required, :default, :example, :min_length, :max_length, :minimum, :maximum, :repeat, :enum, :pattern
106
+
107
+ def initialize(name, type = nil, display_name = nil, description = nil, required = false, default = nil, example = nil, min_length = nil, max_length = nil, minimum = nil, maximum = nil, repeat = nil, enum = nil, pattern = nil)
108
+ @name = name
109
+ @type = type
110
+ @display_name = display_name
111
+ @description = description
112
+ @required = required
113
+ @default = default
114
+ @example = example
115
+ @min_length = min_length
116
+ @max_length = max_length
117
+ @minimum = minimum
118
+ @maximum = maximum
119
+ @repeat = repeat
120
+ @enum = enum
121
+ @pattern = pattern
122
+ end
123
+ end
124
+
125
+ class Documentation
126
+ attr_accessor :title, :content
127
+
128
+ def initialize(title = nil, content = nil)
129
+ @title = title
130
+ @content = content
131
+ end
132
+ end
133
+
134
+ class SecurityScheme
135
+ attr_accessor :name, :type, :description, :described_by, :settings
136
+
137
+ def initialize(name, type = nil, description = nil, described_by = nil, settings = {})
138
+ @name = name
139
+ @type = type
140
+ @description = description
141
+ @described_by = described_by
142
+ @settings = settings
143
+ end
144
+ end
145
+ end
146
+ end