rspec_api_documentation 4.9.0 → 6.1.0

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rspec_api_documentation/api_documentation.rb +2 -0
  3. data/lib/rspec_api_documentation/client_base.rb +8 -8
  4. data/lib/rspec_api_documentation/configuration.rb +12 -1
  5. data/lib/rspec_api_documentation/curl.rb +7 -2
  6. data/lib/rspec_api_documentation/dsl/endpoint/params.rb +19 -3
  7. data/lib/rspec_api_documentation/dsl/endpoint/set_param.rb +18 -5
  8. data/lib/rspec_api_documentation/dsl/endpoint.rb +44 -2
  9. data/lib/rspec_api_documentation/dsl/resource.rb +48 -1
  10. data/lib/rspec_api_documentation/dsl.rb +1 -1
  11. data/lib/rspec_api_documentation/example.rb +4 -0
  12. data/lib/rspec_api_documentation/open_api/contact.rb +9 -0
  13. data/lib/rspec_api_documentation/open_api/example.rb +7 -0
  14. data/lib/rspec_api_documentation/open_api/header.rb +12 -0
  15. data/lib/rspec_api_documentation/open_api/headers.rb +7 -0
  16. data/lib/rspec_api_documentation/open_api/helper.rb +29 -0
  17. data/lib/rspec_api_documentation/open_api/info.rb +12 -0
  18. data/lib/rspec_api_documentation/open_api/license.rb +8 -0
  19. data/lib/rspec_api_documentation/open_api/node.rb +112 -0
  20. data/lib/rspec_api_documentation/open_api/operation.rb +18 -0
  21. data/lib/rspec_api_documentation/open_api/parameter.rb +33 -0
  22. data/lib/rspec_api_documentation/open_api/path.rb +13 -0
  23. data/lib/rspec_api_documentation/open_api/paths.rb +7 -0
  24. data/lib/rspec_api_documentation/open_api/response.rb +10 -0
  25. data/lib/rspec_api_documentation/open_api/responses.rb +9 -0
  26. data/lib/rspec_api_documentation/open_api/root.rb +21 -0
  27. data/lib/rspec_api_documentation/open_api/schema.rb +15 -0
  28. data/lib/rspec_api_documentation/open_api/security_definitions.rb +7 -0
  29. data/lib/rspec_api_documentation/open_api/security_schema.rb +14 -0
  30. data/lib/rspec_api_documentation/open_api/tag.rb +9 -0
  31. data/lib/rspec_api_documentation/railtie.rb +1 -1
  32. data/lib/rspec_api_documentation/views/api_blueprint_example.rb +116 -0
  33. data/lib/rspec_api_documentation/views/api_blueprint_index.rb +105 -0
  34. data/lib/rspec_api_documentation/views/markdown_example.rb +1 -1
  35. data/lib/rspec_api_documentation/views/markup_example.rb +12 -3
  36. data/lib/rspec_api_documentation/views/markup_index.rb +2 -4
  37. data/lib/rspec_api_documentation/views/slate_index.rb +4 -0
  38. data/lib/rspec_api_documentation/writers/api_blueprint_writer.rb +29 -0
  39. data/lib/rspec_api_documentation/writers/combined_json_writer.rb +1 -1
  40. data/lib/rspec_api_documentation/writers/general_markup_writer.rb +20 -7
  41. data/lib/rspec_api_documentation/writers/json_iodocs_writer.rb +3 -2
  42. data/lib/rspec_api_documentation/writers/json_writer.rb +10 -6
  43. data/lib/rspec_api_documentation/writers/markdown_writer.rb +1 -1
  44. data/lib/rspec_api_documentation/writers/open_api_writer.rb +244 -0
  45. data/lib/rspec_api_documentation/writers/slate_writer.rb +2 -8
  46. data/lib/rspec_api_documentation.rb +29 -0
  47. data/templates/rspec_api_documentation/api_blueprint_index.mustache +80 -0
  48. data/templates/rspec_api_documentation/html_index.mustache +1 -1
  49. data/templates/rspec_api_documentation/markdown_example.mustache +4 -3
  50. data/templates/rspec_api_documentation/markdown_index.mustache +1 -0
  51. data/templates/rspec_api_documentation/slate_example.mustache +2 -2
  52. data/templates/rspec_api_documentation/slate_index.mustache +8 -0
  53. data/templates/rspec_api_documentation/textile_index.mustache +1 -0
  54. metadata +61 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16b47e6bedc1c86cc5e418233eca8b80d16b5628
4
- data.tar.gz: e1da890616a2fa4cf6a8ff8c44eff5977abc32f6
3
+ metadata.gz: 8e1f18cb4e1bbf1939b21e8a4bdeb0ca17aae8f2
4
+ data.tar.gz: 98c99830570aad0754d38787cbe528cde8d795f5
5
5
  SHA512:
6
- metadata.gz: c16d4338f5d6e06f1c913a951c1370b31f2e6c85a6aef38a593d5fbd332226ad99c9fae76207e9bed5089500010a5b588a123e0354cdef25d057cbc0483a1933
7
- data.tar.gz: 03ef3fbf5306d2951fa6f3b82f08e2679306069e791ef9bf5d30f58693dbb83528bb78009821cc4b26fb1da166c33620c1e5d327c9d91f8008bd45afa93eead4
6
+ metadata.gz: 000471a180aa638ee4ac2852410f4202f210d3694118a0aafb0b31a7dde2d61baeb1e40fcc45cdfaf149962479de12390ee88096b338e7a6ad979436468ca83e
7
+ data.tar.gz: b2bb72596bdbe8896243c14b69a022e8c820e57fba621c45518ccea38b304c08b165d8b2e910644bbf96af256c989157950785654f91dd554b6a6a7042a85782
@@ -1,3 +1,5 @@
1
+ require 'rspec_api_documentation/writers/json_iodocs_writer'
2
+
1
3
  module RspecApiDocumentation
2
4
  class ApiDocumentation
3
5
  attr_reader :configuration, :index
@@ -96,14 +96,14 @@ module RspecApiDocumentation
96
96
  end
97
97
 
98
98
  def clean_out_uploaded_data(params, request_body)
99
- params.each do |_, value|
100
- if value.is_a?(Hash)
101
- if value.has_key?(:tempfile)
102
- data = value[:tempfile].read
103
- request_body = request_body.gsub(data, "[uploaded data]")
104
- else
105
- request_body = clean_out_uploaded_data(value,request_body)
106
- end
99
+ params.each do |value|
100
+ if [Hash, Array].member? value.class
101
+ request_body = if value.respond_to?(:has_key?) && value.has_key?(:tempfile)
102
+ data = value[:tempfile].read
103
+ request_body.gsub(data, "[uploaded data]")
104
+ else
105
+ clean_out_uploaded_data(value, request_body)
106
+ end
107
107
  end
108
108
  end
109
109
  request_body
@@ -51,6 +51,14 @@ module RspecApiDocumentation
51
51
  end
52
52
  end
53
53
 
54
+ add_setting :configurations_dir, :default => lambda { |config|
55
+ if defined?(Rails)
56
+ Rails.root.join('doc', 'configurations', 'api')
57
+ else
58
+ Pathname.new('doc/configurations/api')
59
+ end
60
+ }
61
+
54
62
  add_setting :docs_dir, :default => lambda { |config|
55
63
  if defined?(Rails)
56
64
  Rails.root.join("doc", "api")
@@ -75,6 +83,7 @@ module RspecApiDocumentation
75
83
  add_setting :curl_host, :default => nil
76
84
  add_setting :keep_source_order, :default => false
77
85
  add_setting :api_name, :default => "API Documentation"
86
+ add_setting :api_explanation, :default => nil
78
87
  add_setting :io_docs_protocol, :default => "http"
79
88
  add_setting :request_headers_to_include, :default => nil
80
89
  add_setting :response_headers_to_include, :default => nil
@@ -109,7 +118,7 @@ module RspecApiDocumentation
109
118
  # See RspecApiDocumentation::DSL::Endpoint#do_request
110
119
  add_setting :response_body_formatter, default: Proc.new { |_, _|
111
120
  Proc.new do |content_type, response_body|
112
- if content_type =~ /application\/json/
121
+ if content_type =~ /application\/.*json/
113
122
  JSON.pretty_generate(JSON.parse(response_body))
114
123
  else
115
124
  response_body
@@ -118,6 +127,8 @@ module RspecApiDocumentation
118
127
  }
119
128
 
120
129
  def client_method=(new_client_method)
130
+ return if new_client_method == client_method
131
+
121
132
  RspecApiDocumentation::DSL::Resource.module_eval <<-RUBY
122
133
  alias :#{new_client_method} #{client_method}
123
134
  undef #{client_method}
@@ -16,7 +16,7 @@ module RspecApiDocumentation
16
16
  end
17
17
 
18
18
  def get
19
- "curl \"#{url}#{get_data}\" -X GET #{headers}"
19
+ "curl -g \"#{url}#{get_data}\" -X GET #{headers}"
20
20
  end
21
21
 
22
22
  def head
@@ -69,7 +69,12 @@ module RspecApiDocumentation
69
69
  end
70
70
 
71
71
  def format_full_header(header, value)
72
- formatted_value = value ? value.gsub(/"/, "\\\"") : ''
72
+ formatted_value = if value.is_a?(Numeric)
73
+ value
74
+ else
75
+ value ? value.gsub(/"/, "\\\"") : ''
76
+ end
77
+
73
78
  "#{format_header(header)}: #{formatted_value}"
74
79
  end
75
80
 
@@ -13,11 +13,27 @@ module RspecApiDocumentation
13
13
  end
14
14
 
15
15
  def call
16
- parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
16
+ set_param = -> hash, param {
17
17
  SetParam.new(self, hash, param).call
18
+ }
19
+
20
+ example.metadata.fetch(:parameters, {}).inject({}, &set_param)
21
+ .deep_merge(
22
+ example.metadata.fetch(:attributes, {}).inject({}, &set_param)
23
+ ).deep_merge(extra_params)
24
+ end
25
+
26
+ def extended
27
+ example.metadata.fetch(:parameters, {}).map do |param|
28
+ p = Marshal.load(Marshal.dump(param))
29
+ p[:value] = SetParam.new(self, nil, p).value
30
+ unless p[:value]
31
+ cur = extra_params
32
+ [*p[:scope]].each { |scope| cur = cur && (cur[scope.to_sym] || cur[scope.to_s]) }
33
+ p[:value] = cur && (cur[p[:name].to_s] || cur[p[:name].to_sym])
34
+ end
35
+ p
18
36
  end
19
- parameters.deep_merge!(extra_params)
20
- parameters
21
37
  end
22
38
 
23
39
  private
@@ -15,6 +15,10 @@ module RspecApiDocumentation
15
15
  hash.deep_merge build_param_hash(key_scope || [key])
16
16
  end
17
17
 
18
+ def value
19
+ example_group.send(method_name) if method_name
20
+ end
21
+
18
22
  private
19
23
 
20
24
  attr_reader :parent, :hash, :param
@@ -36,6 +40,10 @@ module RspecApiDocumentation
36
40
  param[:method]
37
41
  end
38
42
 
43
+ def set_value
44
+ param[:value]
45
+ end
46
+
39
47
  def path_name
40
48
  scoped_key || key
41
49
  end
@@ -45,15 +53,20 @@ module RspecApiDocumentation
45
53
  end
46
54
 
47
55
  def method_name
48
- @method_name ||= begin
49
- [custom_method_name, scoped_key, key].find do |name|
50
- name && example_group.respond_to?(name)
51
- end
56
+ if custom_method_name
57
+ custom_method_name if example_group.respond_to?(custom_method_name)
58
+ elsif scoped_key && example_group.respond_to?(scoped_key)
59
+ scoped_key
60
+ elsif key && example_group.respond_to?(key)
61
+ key
62
+ elsif key && set_value
63
+ key
52
64
  end
53
65
  end
54
66
 
55
67
  def build_param_hash(keys)
56
- value = keys[1] ? build_param_hash(keys[1..-1]) : example_group.send(method_name)
68
+ value = param[:value] if param.has_key?(:value)
69
+ value ||= keys[1] ? build_param_hash(keys[1..-1]) : example_group.send(method_name)
57
70
  { keys[0].to_s => value }
58
71
  end
59
72
  end
@@ -9,6 +9,8 @@ module RspecApiDocumentation::DSL
9
9
  extend ActiveSupport::Concern
10
10
  include Rack::Test::Utils
11
11
 
12
+ URL_PARAMS_REGEX = /[:\{](\w+)\}?/.freeze
13
+
12
14
  delegate :response_headers, :response_status, :response_body, :to => :rspec_api_documentation_client
13
15
 
14
16
  module ClassMethods
@@ -36,6 +38,9 @@ module RspecApiDocumentation::DSL
36
38
  params_or_body = nil
37
39
  path_or_query = path
38
40
 
41
+ extended_parameters
42
+ extract_route_parameters!
43
+
39
44
  if http_method == :get && !query_string.blank?
40
45
  path_or_query += "?#{query_string}"
41
46
  else
@@ -72,6 +77,36 @@ module RspecApiDocumentation::DSL
72
77
  example.metadata[:headers][name] = value
73
78
  end
74
79
 
80
+ def authentication(type, value, opts = {})
81
+ name, new_opts =
82
+ case type
83
+ when :basic then ['Authorization', opts.merge(type: type)]
84
+ when :apiKey then [opts[:name], opts.merge(type: type, in: :header)]
85
+ else raise 'Not supported type for authentication'
86
+ end
87
+ header(name, value)
88
+ example.metadata[:authentications] ||= {}
89
+ example.metadata[:authentications][name] = new_opts
90
+ end
91
+
92
+ def extract_route_parameters!
93
+ example.metadata[:route].gsub(URL_PARAMS_REGEX) do |match|
94
+ value =
95
+ if extra_params.keys.include?($1)
96
+ extra_params[$1]
97
+ elsif respond_to?($1)
98
+ send($1)
99
+ else
100
+ match
101
+ end
102
+ extended_parameters << {name: match[1..-1], value: value, in: :path}
103
+ end
104
+ end
105
+
106
+ def extended_parameters
107
+ example.metadata[:extended_parameters] ||= Params.new(self, example, extra_params).extended
108
+ end
109
+
75
110
  def headers
76
111
  return unless example.metadata[:headers]
77
112
  example.metadata[:headers].inject({}) do |hash, (header, value)|
@@ -96,8 +131,16 @@ module RspecApiDocumentation::DSL
96
131
  rspec_api_documentation_client.status
97
132
  end
98
133
 
134
+ def in_path?(param)
135
+ path_params.include?(param)
136
+ end
137
+
138
+ def path_params
139
+ example.metadata[:route].scan(URL_PARAMS_REGEX).flatten
140
+ end
141
+
99
142
  def path
100
- example.metadata[:route].gsub(/:(\w+)/) do |match|
143
+ example.metadata[:route].gsub(URL_PARAMS_REGEX) do |match|
101
144
  if extra_params.keys.include?($1)
102
145
  delete_extra_param($1)
103
146
  elsif respond_to?($1)
@@ -134,6 +177,5 @@ module RspecApiDocumentation::DSL
134
177
  def delete_extra_param(key)
135
178
  @extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
136
179
  end
137
-
138
180
  end
139
181
  end
@@ -8,7 +8,12 @@ module RspecApiDocumentation::DSL
8
8
  define_method method do |*args, &block|
9
9
  options = args.extract_options!
10
10
  options[:method] = method
11
- options[:route] = args.first
11
+ if metadata[:route_uri]
12
+ options[:route] = metadata[:route_uri]
13
+ options[:action_name] = args.first
14
+ else
15
+ options[:route] = args.first
16
+ end
12
17
  options[:api_doc_dsl] = :endpoint
13
18
  args.push(options)
14
19
  args[0] = "#{method.to_s.upcase} #{args[0]}"
@@ -38,10 +43,25 @@ module RspecApiDocumentation::DSL
38
43
  context(*args, &block)
39
44
  end
40
45
 
46
+ def route(*args, &block)
47
+ raise "You must define the route URI" if args[0].blank?
48
+ raise "You must define the route name" if args[1].blank?
49
+ options = args.extract_options!
50
+ options[:route_uri] = args[0].gsub(/\{.*\}/, "")
51
+ options[:route_optionals] = (optionals = args[0].match(/(\{.*\})/) and optionals[-1])
52
+ options[:route_name] = args[1]
53
+ args.push(options)
54
+ context(*args, &block)
55
+ end
56
+
41
57
  def parameter(name, *args)
42
58
  parameters.push(field_specification(name, *args))
43
59
  end
44
60
 
61
+ def attribute(name, *args)
62
+ attributes.push(field_specification(name, *args))
63
+ end
64
+
45
65
  def response_field(name, *args)
46
66
  response_fields.push(field_specification(name, *args))
47
67
  end
@@ -50,6 +70,25 @@ module RspecApiDocumentation::DSL
50
70
  headers[name] = value
51
71
  end
52
72
 
73
+ def authentication(type, value, opts = {})
74
+ name, new_opts =
75
+ case type
76
+ when :basic then ['Authorization', opts.merge(type: type)]
77
+ when :apiKey then [opts[:name], opts.merge(type: type, in: :header)]
78
+ else raise 'Not supported type for authentication'
79
+ end
80
+ header(name, value)
81
+ authentications[name] = new_opts
82
+ end
83
+
84
+ def route_summary(text)
85
+ safe_metadata(:route_summary, text)
86
+ end
87
+
88
+ def route_description(text)
89
+ safe_metadata(:route_description, text)
90
+ end
91
+
53
92
  def explanation(text)
54
93
  safe_metadata(:resource_explanation, text)
55
94
  end
@@ -75,6 +114,10 @@ module RspecApiDocumentation::DSL
75
114
  safe_metadata(:parameters, [])
76
115
  end
77
116
 
117
+ def attributes
118
+ safe_metadata(:attributes, [])
119
+ end
120
+
78
121
  def response_fields
79
122
  safe_metadata(:response_fields, [])
80
123
  end
@@ -83,6 +126,10 @@ module RspecApiDocumentation::DSL
83
126
  safe_metadata(:headers, {})
84
127
  end
85
128
 
129
+ def authentications
130
+ safe_metadata(:authentications, {})
131
+ end
132
+
86
133
  def parameter_keys
87
134
  parameters.map { |param| param[:name] }
88
135
  end
@@ -21,7 +21,7 @@ module RspecApiDocumentation
21
21
  options = args.last.is_a?(Hash) ? args.pop : {}
22
22
  options[:api_doc_dsl] = :resource
23
23
  options[:resource_name] = args.first.to_s
24
- options[:document] ||= :all
24
+ options[:document] = :all unless options.key?(:document)
25
25
  args.push(options)
26
26
  describe(*args, &block)
27
27
  end
@@ -38,6 +38,10 @@ module RspecApiDocumentation
38
38
  respond_to?(:parameters) && parameters.present?
39
39
  end
40
40
 
41
+ def has_attributes?
42
+ respond_to?(:attributes) && attributes.present?
43
+ end
44
+
41
45
  def has_response_fields?
42
46
  respond_to?(:response_fields) && response_fields.present?
43
47
  end
@@ -0,0 +1,9 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Contact < Node
4
+ add_setting :name, :default => 'API Support'
5
+ add_setting :url, :default => 'http://www.open-api.io/support'
6
+ add_setting :email, :default => 'support@open-api.io'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Example < Node
4
+ CHILD_CLASS = true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Header < Node
4
+ add_setting :description, :default => ''
5
+ add_setting :type, :required => true, :default => lambda { |header|
6
+ Helper.extract_type(header.public_send('x-example-value'))
7
+ }
8
+ add_setting :format
9
+ add_setting 'x-example-value'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Headers < Node
4
+ CHILD_CLASS = Header
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ module Helper
4
+ module_function
5
+
6
+ def extract_type(value)
7
+ case value
8
+ when Rack::Test::UploadedFile then :file
9
+ when Array then :array
10
+ when Hash then :object
11
+ when TrueClass, FalseClass then :boolean
12
+ when Integer then :integer
13
+ when Float then :number
14
+ else :string
15
+ end
16
+ end
17
+
18
+ def extract_items(value, opts = {})
19
+ result = {type: extract_type(value)}
20
+ if result[:type] == :array
21
+ result[:items] = extract_items(value[0], opts)
22
+ else
23
+ opts.each { |k, v| result[k] = v if v }
24
+ end
25
+ result
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Info < Node
4
+ add_setting :title, :default => 'OpenAPI Specification', :required => true
5
+ add_setting :description, :default => 'This is a sample server Petstore server.'
6
+ add_setting :termsOfService, :default => 'http://open-api.io/terms/'
7
+ add_setting :contact, :default => Contact.new, :schema => Contact
8
+ add_setting :license, :default => License.new, :schema => License
9
+ add_setting :version, :default => '1.0.0', :required => true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class License < Node
4
+ add_setting :name, :default => 'Apache 2.0', :required => true
5
+ add_setting :url, :default => 'http://www.apache.org/licenses/LICENSE-2.0.html'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,112 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Node
4
+ # this is used to define class of incoming option attribute
5
+ # If +false+ then do not create new setting
6
+ # If +true+ then create new setting with raw passed value
7
+ # If RspecApiDocumentation::OpenApi::Node then create new setting and wrap it in this class
8
+ CHILD_CLASS = false
9
+
10
+ # This attribute allow us to hide some of children through configuration file
11
+ attr_accessor :hide
12
+
13
+ def self.add_setting(name, opts = {})
14
+ class_settings << name
15
+
16
+ define_method("#{name}_schema") { opts[:schema] || NilClass }
17
+ define_method("#{name}=") { |value| settings[name] = value }
18
+ define_method("#{name}") do
19
+ if settings.has_key?(name)
20
+ settings[name]
21
+ elsif !opts[:default].nil?
22
+ if opts[:default].respond_to?(:call)
23
+ opts[:default].call(self)
24
+ else
25
+ opts[:default]
26
+ end
27
+ elsif opts[:required]
28
+ raise "setting: #{name} required in #{self}"
29
+ end
30
+ end
31
+ end
32
+
33
+ def initialize(opts = {})
34
+ return unless opts
35
+
36
+ opts.each do |name, value|
37
+ if name.to_s == 'hide'
38
+ self.hide = value
39
+ elsif self.class::CHILD_CLASS
40
+ add_setting name, :value => self.class::CHILD_CLASS === true ? value : self.class::CHILD_CLASS.new(value)
41
+ elsif setting_exist?(name.to_sym)
42
+ schema = setting_schema(name)
43
+ converted =
44
+ case
45
+ when schema.is_a?(Array) && schema[0] <= Node then value.map { |v| v.is_a?(schema[0]) ? v : schema[0].new(v) }
46
+ when schema <= Node then value.is_a?(schema) ? value : schema.new(value)
47
+ else
48
+ value
49
+ end
50
+ assign_setting(name, converted)
51
+ else
52
+ public_send("#{name}=", value) if respond_to?("#{name}=")
53
+ end
54
+ end
55
+ end
56
+
57
+ def assign_setting(name, value); public_send("#{name}=", value) unless value.nil? end
58
+ def safe_assign_setting(name, value); assign_setting(name, value) unless settings.has_key?(name) end
59
+ def setting(name); public_send(name) end
60
+ def setting_schema(name); public_send("#{name}_schema") end
61
+ def setting_exist?(name); existing_settings.include?(name) end
62
+ def existing_settings; self.class.class_settings + instance_settings end
63
+
64
+ def add_setting(name, opts = {})
65
+ return false if setting_exist?(name)
66
+
67
+ instance_settings << name
68
+
69
+ settings[name] = opts[:value] if opts[:value]
70
+
71
+ define_singleton_method("#{name}_schema") { opts[:schema] || NilClass }
72
+ define_singleton_method("#{name}=") { |value| settings[name] = value }
73
+ define_singleton_method("#{name}") do
74
+ if settings.has_key?(name)
75
+ settings[name]
76
+ elsif !opts[:default].nil?
77
+ if opts[:default].respond_to?(:call)
78
+ opts[:default].call(self)
79
+ else
80
+ opts[:default]
81
+ end
82
+ elsif opts[:required]
83
+ raise "setting: #{name} required in #{self}"
84
+ end
85
+ end
86
+ end
87
+
88
+ def as_json
89
+ existing_settings.inject({}) do |hash, name|
90
+ value = setting(name)
91
+ case
92
+ when value.is_a?(Node)
93
+ hash[name] = value.as_json unless value.hide
94
+ when value.is_a?(Array) && value[0].is_a?(Node)
95
+ tmp = value.select { |v| !v.hide }.map { |v| v.as_json }
96
+ hash[name] = tmp unless tmp.empty?
97
+ else
98
+ hash[name] = value
99
+ end unless value.nil?
100
+
101
+ hash
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def settings; @settings ||= {} end
108
+ def instance_settings; @instance_settings ||= [] end
109
+ def self.class_settings; @class_settings ||= [] end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,18 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Operation < Node
4
+ add_setting :tags, :default => []
5
+ add_setting :summary
6
+ add_setting :description, :default => ''
7
+ add_setting :externalDocs
8
+ add_setting :operationId
9
+ add_setting :consumes
10
+ add_setting :produces
11
+ add_setting :parameters, :default => [], :schema => [Parameter]
12
+ add_setting :responses, :required => true, :schema => Responses
13
+ add_setting :schemes
14
+ add_setting :deprecated, :default => false
15
+ add_setting :security
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Parameter < Node
4
+ # Required to write example values to description of parameter when option `with_example: true` is provided
5
+ attr_accessor :value
6
+ attr_accessor :with_example
7
+
8
+ add_setting :name, :required => true
9
+ add_setting :in, :required => true
10
+ add_setting :description, :default => ''
11
+ add_setting :required, :default => lambda { |parameter| parameter.in.to_s == 'path' ? true : false }
12
+ add_setting :schema
13
+ add_setting :type
14
+ add_setting :items
15
+ add_setting :default
16
+ add_setting :minimum
17
+ add_setting :maximum
18
+ add_setting :enum
19
+
20
+ def description_with_example
21
+ str = description_without_example.dup || ''
22
+ if with_example && value
23
+ str << "\n" unless str.empty?
24
+ str << "Eg, `#{value}`"
25
+ end
26
+ str
27
+ end
28
+
29
+ alias_method :description_without_example, :description
30
+ alias_method :description, :description_with_example
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Path < Node
4
+ add_setting :get, :schema => Operation
5
+ add_setting :put, :schema => Operation
6
+ add_setting :post, :schema => Operation
7
+ add_setting :delete, :schema => Operation
8
+ add_setting :options, :schema => Operation
9
+ add_setting :head, :schema => Operation
10
+ add_setting :patch, :schema => Operation
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Paths < Node
4
+ CHILD_CLASS = Path
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module RspecApiDocumentation
2
+ module OpenApi
3
+ class Response < Node
4
+ add_setting :description, :required => true, :default => 'Successful operation'
5
+ add_setting :schema, :schema => Schema
6
+ add_setting :headers, :schema => Headers
7
+ add_setting :examples, :schema => Example
8
+ end
9
+ end
10
+ end