zero-rails_openapi 1.5.2 → 1.5.3

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.
@@ -54,7 +54,7 @@ class Api::V1::ExamplesController < Api::V1::BaseController
54
54
  :name! => String, # <= schema_type is `String`
55
55
  :password! => { type: String, pattern: /[0-9]{6,10}/, desc: 'password' },
56
56
  # optional
57
- :remarks => { type: String, desc: 'remarks' }, # <= schema_type is `String`, and schema_hash is { desc: '..' }
57
+ :remarks => { type: String, desc: 'remarks' }, # <= schema_type is `String`, and schema_info is { desc: '..' }
58
58
  }
59
59
  end
60
60
  end
@@ -1,4 +1,4 @@
1
- ### More Explanation for `param` and `schema_hash`
1
+ ### More Explanation for `param` and `schema_info`
2
2
 
3
3
  #### param_type (param_location)
4
4
  OpenAPI 3.0 distinguishes between the following parameter types based on the parameter location:
@@ -15,7 +15,7 @@ Parameter's (schema) type. We call it `schema_type` because it is inside SchemaO
15
15
 
16
16
  Support all [data types](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#dataTypes) defined in OAS.
17
17
 
18
- In addition, you can use `format` in schema_hash to define in fine detail the data type being used, like:
18
+ In addition, you can use `format` in schema_info to define in fine detail the data type being used, like:
19
19
  int32, float, date ...
20
20
  All the types you can use as following:
21
21
  - **String, 'binary', 'base64'**
@@ -41,7 +41,7 @@ All the types you can use as following:
41
41
  #### Schema Hash
42
42
 
43
43
  The [[schema]](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#schemaObject) defining the type used for the parameter.
44
- schema_hash(optional) will be used to generate Schema Object inside Parameter Object.
44
+ schema_info(optional) will be used to generate Schema Object inside Parameter Object.
45
45
  [source code](https://github.com/zhandao/zero-rails_openapi/blob/master/lib/oas_objs/schema_obj.rb)
46
46
  You can set the schema by following keys (all are optional), the words in parentheses are available aliases of the keys:
47
47
  - **enum (values, allowable_values)**
@@ -19,29 +19,18 @@ module OpenApi
19
19
  end
20
20
 
21
21
  def process
22
- assign(desc).to_processed 'description'
23
- processed.tap { |it| it[:schema] = schema.process }
22
+ assign(desc).to_processed :description
23
+ assign(schema.process).to_processed :schema
24
+ processed
24
25
  end
25
26
 
26
27
  def desc
27
- return _desc unless __desc.present?
28
- schema.preprocess_with_desc __desc
28
+ return self[:desc] || self[:description] if (self[:desc!] || self[:description!]).blank?
29
+ schema.__desc # not a copy of __desc, means desc() will change if schema.__desc changes.
29
30
  end
30
31
 
31
-
32
- # Getters and Setters of the original values that was passed to param()
33
- # This mapping allows user to select the aliases in DSL writing,
34
- # without increasing the complexity of the implementation.
35
- { # SELF_MAPPING
36
- _range: %i[ range number_range ],
37
- _length: %i[ length lth ],
38
- _desc: %i[ desc description ],
39
- __desc: %i[ desc! description! ],
40
- }.each do |key, aliases|
41
- define_method key do
42
- aliases.each { |alias_name| self[key] ||= self[alias_name] } if self[key].nil?
43
- self[key]
44
- end
32
+ def name
33
+ processed[:name]
45
34
  end
46
35
  end
47
36
  end
@@ -13,7 +13,8 @@ module OpenApi
13
13
  }
14
14
  end
15
15
 
16
- def process; processed; end
16
+ def process; processed end
17
+ def name; nil end
17
18
  end
18
19
  end
19
20
  end
@@ -13,55 +13,30 @@ module OpenApi
13
13
 
14
14
  attr_accessor :processed, :type, :preprocessed
15
15
 
16
- def initialize(type, schema_hash)
16
+ def initialize(type, schema_info)
17
17
  self.preprocessed = false
18
18
  self.processed = { }
19
- # [Note] Here is no limit to type, even if the input isn't up to OAS,
20
- # like: double, float, hash.
21
- # My consideration is, OAS can't express some cases like:
22
- # `total_price` should be double, is_a `price`, and match /^.*\..*$/
23
- # However, user can decide how to write --
24
- # `type: number, format: double`, or `type: double`
25
19
  self.type = type
26
- merge! schema_hash
20
+ merge! schema_info
27
21
  end
28
22
 
29
23
  def process(options = { inside_desc: false })
30
- return processed if preprocessed
31
-
32
24
  processed.merge!(processed_type)
33
- reducx(
34
- processed_enum_and_length,
35
- processed_range,
36
- processed_is_and_format,
37
- {
38
- pattern: _pattern.is_a?(String)? _pattern : _pattern&.inspect&.delete('/'),
39
- default: _default,
40
- examples: self[:examples].present? ? ExampleObj.new(self[:examples], self[:exp_by]).process : nil
41
- },
42
- { as: _as, permit: _permit, not_permit: _npermit, req_if: _req_if, opt_if: _opt_if, blankable: _blank },
43
- ).then_merge!
44
- reducx(processed_desc(options)).then_merge! # TODO
45
- end
46
-
47
- def preprocess_with_desc desc
48
- self.__desc = desc
49
- process
50
- self.preprocessed = true
51
- __desc
25
+ reducx(enum_and_length, range, is_and_format, pattern_default_and_other, desc(options)).then_merge!
52
26
  end
53
27
 
54
- def processed_desc(options)
28
+ def desc(inside_desc:)
55
29
  result = __desc ? auto_generate_desc : _desc
56
- options[:inside_desc] ? { description: result } : nil
30
+ return unless inside_desc
31
+ { description: result }
57
32
  end
58
33
 
59
34
  def processed_type(type = self.type)
60
35
  t = type.class.in?([Hash, Array, Symbol]) ? type : type.to_s.downcase
61
36
  if t.is_a? Hash
62
- processed_hash_type(t)
37
+ hash_type(t)
63
38
  elsif t.is_a? Array
64
- processed_array_type(t)
39
+ array_type(t)
65
40
  elsif t.is_a? Symbol
66
41
  RefObj.new(:schema, t).process
67
42
  elsif t.in? %w[ float double int32 int64 ]
@@ -77,33 +52,17 @@ module OpenApi
77
52
  end
78
53
  end
79
54
 
80
- def processed_hash_type(t)
81
- # For supporting this:
82
- # form 'desc', type: {
83
- # id!: { type: Integer, enum: 0..5, desc: 'user id' }
84
- # }, should have description within schema
85
- if t.key?(:type)
86
- SchemaObj.new(t[:type], t).process(inside_desc: true)
87
-
88
- # For supporting combined schema in nested schema.
89
- elsif (t.keys & %i[ one_of any_of all_of not ]).present?
90
- CombinedSchema.new(t).process(inside_desc: true)
91
- else
92
- processed_obj_type(t)
93
- end
94
- end
95
-
96
- def processed_enum_and_length
55
+ def enum_and_length
97
56
  process_enum_info
98
57
  process_range_enum_and_lth
99
58
 
100
59
  # generate length range fields by _lth array
101
- if (lth = _length || [ ]).is_a?(Array)
60
+ if (lth = _length || '').is_a?(Array)
102
61
  min, max = [lth.first&.to_i, lth.last&.to_i]
103
62
  elsif lth['ge']
104
- max = lth.to_s.split('_').last.to_i
105
- elsif lth['le']
106
63
  min = lth.to_s.split('_').last.to_i
64
+ elsif lth['le']
65
+ max = lth.to_s.split('_').last.to_i
107
66
  end
108
67
 
109
68
  if processed[:type] == 'array'
@@ -113,23 +72,32 @@ module OpenApi
113
72
  end.merge!(enum: _enum).keep_if &value_present
114
73
  end
115
74
 
116
- def processed_range
75
+ def range
117
76
  range = _range || { }
118
77
  {
119
- minimum: range[:gt] || range[:ge],
78
+ minimum: range[:gt] || range[:ge],
120
79
  exclusiveMinimum: range[:gt].present? ? true : nil,
121
- maximum: range[:lt] || range[:le],
80
+ maximum: range[:lt] || range[:le],
122
81
  exclusiveMaximum: range[:lt].present? ? true : nil
123
82
  }.keep_if &value_present
124
83
  end
125
84
 
126
- def processed_is_and_format
85
+ def is_and_format
127
86
  result = { is: _is }
128
87
  # `format` that generated in process_type() may be overwrote here.
129
88
  result[:format] = _format || _is if processed[:format].blank? || _format.present?
130
89
  result
131
90
  end
132
91
 
92
+ def pattern_default_and_other
93
+ {
94
+ pattern: _pattern.is_a?(String)? _pattern : _pattern&.inspect&.delete('/'),
95
+ default: _default,
96
+ examples: self[:examples].present? ? ExampleObj.new(self[:examples], self[:exp_by]).process : nil,
97
+ as: _as, permit: _permit, not_permit: _npermit, req_if: _req_if, opt_if: _opt_if, blankable: _blank
98
+ }
99
+ end
100
+
133
101
 
134
102
  { # SELF_MAPPING
135
103
  _enum: %i[ enum in values allowable_values ],
@@ -151,11 +119,7 @@ module OpenApi
151
119
  }.each do |key, aliases|
152
120
  define_method key do
153
121
  return self[key] unless self[key].nil?
154
-
155
- aliases.each do |alias_name|
156
- break if self[key] == false
157
- self[key] ||= self[alias_name]
158
- end
122
+ aliases.each { |alias_name| self[key] = self[alias_name] if self[key].nil? }
159
123
  self[key]
160
124
  end
161
125
  define_method "#{key}=" do |value| self[key] = value end
@@ -1,23 +1,23 @@
1
1
  module OpenApi
2
2
  module DSL
3
3
  module SchemaObjHelpers
4
- # TODO: more info and desc configure
5
- def auto_generate_desc
6
- return __desc if processed[:enum].blank?
4
+ def hash_type(t)
5
+ # For supporting this:
6
+ # form 'desc', type: {
7
+ # id!: { type: Integer, enum: 0..5, desc: 'user id' }
8
+ # }, should have description within schema
9
+ if t.key?(:type)
10
+ SchemaObj.new(t[:type], t).process(inside_desc: true)
7
11
 
8
- if @enum_info.present?
9
- @enum_info.each_with_index do |(info, value), index|
10
- __desc.concat "<br/>#{index + 1}/ #{info}: #{value}"
11
- end
12
+ # For supporting combined schema in nested schema.
13
+ elsif (t.keys & %i[ one_of any_of all_of not ]).present?
14
+ CombinedSchema.new(t).process(inside_desc: true)
12
15
  else
13
- processed[:enum].each_with_index do |value, index|
14
- __desc.concat "<br/>#{index + 1}/ #{value}"
15
- end
16
+ obj_type(t)
16
17
  end
17
- __desc
18
18
  end
19
19
 
20
- def processed_obj_type(t)
20
+ def obj_type(t)
21
21
  obj_type = { type: 'object', properties: { }, required: [ ] }
22
22
 
23
23
  t.each do |prop_name, prop_type|
@@ -27,7 +27,7 @@ module OpenApi
27
27
  obj_type.keep_if &value_present
28
28
  end
29
29
 
30
- def processed_array_type(t)
30
+ def array_type(t)
31
31
  t = t.size == 1 ? t.first : { one_of: t }
32
32
  {
33
33
  type: 'array',
@@ -36,16 +36,16 @@ module OpenApi
36
36
  end
37
37
 
38
38
  def process_range_enum_and_lth
39
- self[:_enum] = str_range_2a(_enum) if _enum.present? && _enum.is_a?(Range)
40
- self[:_length] = str_range_2a(_length) if _length.present? && _length.is_a?(Range)
39
+ self[:_enum] = str_range_toa(_enum) if _enum.is_a?(Range)
40
+ self[:_length] = str_range_toa(_length) if _length.is_a?(Range)
41
41
 
42
42
  values = _enum || _value
43
43
  self._enum = Array(values) if truly_present?(values)
44
44
  end
45
45
 
46
- def str_range_2a(val)
46
+ def str_range_toa(val)
47
47
  val_class = val.first.class
48
- action = "to_#{val_class.to_s.downcase[0]}".to_sym
48
+ action = :"to_#{val_class.to_s.downcase[0]}"
49
49
  (val.first.to_s..val.last.to_s).to_a.map(&action)
50
50
  end
51
51
 
@@ -55,10 +55,26 @@ module OpenApi
55
55
  # 'all_desc': :all,
56
56
  # 'one_desc': :one
57
57
  # }
58
- self._enum ||= self[:enum!]
59
- return unless self[:enum!].is_a? Hash
60
- @enum_info = self[:enum!]
61
- self._enum = self[:enum!].values
58
+ self._enum ||= e = self[:enum!]
59
+ return unless e.is_a? Hash
60
+ @enum_info = e
61
+ self._enum = e.values
62
+ end
63
+
64
+ # TODO: more info and desc configure
65
+ def auto_generate_desc
66
+ return __desc if _enum.blank?
67
+
68
+ if @enum_info.present?
69
+ @enum_info.each_with_index do |(info, value), index|
70
+ __desc.concat "<br/>#{index + 1}/ #{info}: #{value}"
71
+ end
72
+ else
73
+ _enum.each_with_index do |value, index|
74
+ __desc.concat "<br/>#{index + 1}/ #{value}"
75
+ end
76
+ end
77
+ __desc
62
78
  end
63
79
  end
64
80
  end
@@ -28,27 +28,22 @@ module OpenApi
28
28
  self[:description] = desc
29
29
  end
30
30
 
31
- def param param_type, name, type, required, schema_hash = { }
31
+ def param param_type, name, type, required, schema_info = { }
32
32
  return if param_skip.include?(name)
33
33
  return if param_use.present? && param_use.exclude?(name)
34
34
 
35
- _t = nil
36
- schema_hash[:desc] ||= _t if (_t = param_descs[name]).present?
37
- schema_hash[:desc!] ||= _t if (_t = param_descs["#{name}!".to_sym]).present?
38
-
39
- param_obj = ParamObj.new(name, param_type, type, required, schema_hash)
35
+ schema_info[:desc] ||= param_descs[name]
36
+ schema_info[:desc!] ||= param_descs[:"#{name}!"]
37
+ param_obj = ParamObj.new(name, param_type, type, required, schema_info)
40
38
  # The definition of the same name parameter will be overwritten
41
39
  fill_in_parameters(param_obj)
42
40
  end
43
41
 
44
42
  # [ header header! path path! query query! cookie cookie! ]
45
- def _param_agent name, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash
46
- combined_schema = one_of || all_of || any_of || (_not = binding.local_variable_get(:not))
47
- type = schema_hash[:type] ||= type
48
- pp "[ZRO] Syntax Error: param `#{name}` has no schema type!" and return if type.nil? && combined_schema.nil?
49
-
50
- schema_hash = CombinedSchema.new(one_of: one_of, all_of: all_of, any_of: any_of, _not: _not) if combined_schema
51
- param @param_type.to_s.delete('!'), name, type, (@param_type['!'] ? :req : :opt), schema_hash
43
+ def _param_agent name, type = nil, **schema_info
44
+ schema = process_schema_info(type, schema_info)
45
+ return puts ' ZRO'.red + " Syntax Error: param `#{name}` has no schema type!" if schema[:illegal?]
46
+ param @param_type, name, schema[:type], @necessity, schema[:combined] || schema[:info]
52
47
  end
53
48
 
54
49
  # For supporting this: (just like `form '', data: { }` usage)
@@ -58,17 +53,17 @@ module OpenApi
58
53
  # }
59
54
  %i[ header header! path path! query query! cookie cookie! ].each do |param_type|
60
55
  define_method "do_#{param_type}" do |by:, **common_schema|
61
- by.each do |p_name, schema|
62
- action = param_type.to_s.delete('!')
56
+ by.each do |param_name, schema|
57
+ action = "#{param_type}#{param_name['!']}".sub('!!', '!')
63
58
  type, schema = schema.is_a?(Hash) ? [schema[:type], schema] : [schema, { }]
64
- args = [ p_name.to_s.delete('!').to_sym, type, schema.reverse_merge!(common_schema) ]
65
- param_type['!'] || p_name['!'] ? send("#{action}!", *args) : send(action, *args)
59
+ args = [ param_name.to_s.delete('!').to_sym, type, schema.reverse_merge!(common_schema) ]
60
+ send(action, *args)
66
61
  end
67
62
  end
68
63
  end
69
64
 
70
65
  def param_ref component_key, *keys
71
- self[:parameters].concat([component_key].concat(keys).map { |key| RefObj.new(:parameter, key).process })
66
+ self[:parameters] += [component_key, *keys].map { |key| RefObj.new(:parameter, key) }
72
67
  end
73
68
 
74
69
  # options: `exp_by` and `examples`
@@ -80,7 +75,7 @@ module OpenApi
80
75
 
81
76
  # [ body body! ]
82
77
  def _request_body_agent media_type, data: { }, **options
83
- request_body (@method_name['!'] ? :req : :opt), media_type, data: data, **options
78
+ request_body @necessity, media_type, data: data, **options
84
79
  end
85
80
 
86
81
  def body_ref component_key
@@ -95,9 +90,9 @@ module OpenApi
95
90
  body! :form, data: data, **options
96
91
  end
97
92
 
98
- def data name, type = nil, schema_hash = { }
99
- schema_hash[:type] = type if type.present?
100
- form data: { name => schema_hash }
93
+ def data name, type = nil, schema_info = { }
94
+ schema_info[:type] = type if type.present?
95
+ form data: { name => schema_info }
101
96
  end
102
97
 
103
98
  def file media_type, data: { type: File }, **options
@@ -109,9 +104,7 @@ module OpenApi
109
104
  end
110
105
 
111
106
  def response_ref code_compkey_hash
112
- code_compkey_hash.each do |code, component_key|
113
- self[:responses][code] = RefObj.new(:response, component_key).process
114
- end
107
+ code_compkey_hash.each { |code, component_key| self[:responses][code] = RefObj.new(:response, component_key) }
115
108
  end
116
109
 
117
110
  def security_require scheme_name, scopes: [ ]
@@ -128,34 +121,24 @@ module OpenApi
128
121
 
129
122
  def order *param_names
130
123
  self.param_order = param_names
131
- # use when api_dry
124
+ # be used when `api_dry`
132
125
  self.param_use = param_order if param_use.blank?
133
126
  self.param_skip = param_use - param_order
134
127
  end
135
128
 
136
129
  def param_examples exp_by = :all, examples_hash
137
- process_objs
138
- exp_by = self[:parameters].map { |p| p[:name] } if exp_by == :all
130
+ exp_by = self[:parameters].map(&:name) if exp_by == :all
139
131
  self[:examples] = ExampleObj.new(examples_hash, exp_by).process
140
132
  end
141
133
 
142
134
  alias examples param_examples
143
135
 
144
136
  def process_objs
145
- self[:parameters]&.each_with_index do |p, index|
146
- self[:parameters][index] = p.process if p.is_a?(ParamObj)
147
- end
137
+ self[:parameters].map!(&:process)
138
+ self[:parameters].sort_by! { |param| param_order.index(param[:name]) || Float::INFINITY } if param_order.present?
148
139
 
149
- # Parameters sorting
150
- self[:parameters].clone.each do |p|
151
- self[:parameters][param_order.index(p[:name]) || -1] = p
152
- end if param_order.present?
153
-
154
- self[:requestBody] = self[:requestBody].try :process
155
-
156
- self[:responses]&.each do |code, obj|
157
- self[:responses][code] = obj.process if obj.is_a?(ResponseObj)
158
- end
140
+ self[:requestBody] = self[:requestBody].try(:process)
141
+ self[:responses].each { |code, response| self[:responses][code] = response.process }
159
142
  end
160
143
  end
161
144
  end
@@ -12,14 +12,15 @@ module OpenApi
12
12
  module CommonDSL
13
13
  %i[ header header! path path! query query! cookie cookie! ].each do |param_type|
14
14
  define_method param_type do |*args|
15
- @param_type = param_type
15
+ @necessity = param_type['!'] ? :req : :opt
16
+ @param_type = param_type.to_s.delete('!') # OR: caller[0][/`.*'/][1..-2].to_sym
16
17
  _param_agent *args
17
18
  end
18
19
  end
19
20
 
20
21
  %i[ body body! ].each do |method|
21
22
  define_method method do |*args|
22
- @method_name = method
23
+ @necessity = method['!'] ? :req : :opt
23
24
  _request_body_agent *args
24
25
  end
25
26
  end
@@ -6,51 +6,44 @@ module OpenApi
6
6
  include DSL::CommonDSL
7
7
  include DSL::Helpers
8
8
 
9
- def schema component_key, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash
10
- combined_schema = (_not = binding.local_variable_get(:not)) || one_of || all_of || any_of
11
- schema_hash[:type] ||= type
12
- schema_hash = load_schema component_key if component_key.try(:superclass) == (Config.active_record_base || ApplicationRecord)
13
- pp "[ZRO] Syntax Error: component schema `#{component_key}` has no type!" and return if schema_hash[:type].nil? && combined_schema.nil?
14
-
15
- combined_schema = CombinedSchema.new(one_of: one_of, all_of: all_of, any_of: any_of, _not: _not) if combined_schema
16
- (self[:schemas] ||= { })[component_key.to_s.to_sym] = combined_schema&.process || SchemaObj.new(schema_hash, { }).process
9
+ def schema component_key, type = nil, **schema_info
10
+ schema = process_schema_info(type, schema_info, model: component_key)
11
+ return puts ' ZRO'.red + " Syntax Error: component schema `#{component_key}` has no type!" if schema[:illegal?]
12
+ self[:schemas][component_key.to_s.to_sym] = (schema[:combined] || SchemaObj.new(type = schema[:info], { })).process
17
13
  end
14
+
18
15
  arrow_enable :schema
19
16
 
20
17
  def example component_key, examples_hash
21
- (self[:examples] ||= { })[component_key] = ExampleObj.new(examples_hash).process
18
+ self[:examples][component_key] = ExampleObj.new(examples_hash).process
22
19
  end
20
+
23
21
  arrow_enable :example
24
22
 
25
- def param component_key, param_type, name, type, required, schema_hash = { }
26
- (self[:parameters] ||= { })[component_key] = ParamObj.new(name, param_type, type, required, schema_hash).process
23
+ def param component_key, param_type, name, type, required, schema_info = { }
24
+ self[:parameters][component_key] = ParamObj.new(name, param_type, type, required, schema_info).process
27
25
  end
28
26
 
29
27
  # [ header header! path path! query query! cookie cookie! ]
30
- def _param_agent component_key, name, type = nil, one_of: nil, all_of: nil, any_of: nil, not: nil, **schema_hash
31
- combined_schema = one_of || all_of || any_of || (_not = binding.local_variable_get(:not))
32
- schema_hash[:type] ||= type
33
- pp "[ZRO] Syntax Error: param `#{name}` has no schema type!" and return if schema_hash[:type].nil? && combined_schema.nil?
34
-
35
- combined_schema = one_of || all_of || any_of || (_not = binding.local_variable_get(:not))
36
- schema_hash = CombinedSchema.new(one_of: one_of, all_of: all_of, any_of: any_of, _not: _not) if combined_schema
37
- param component_key,
38
- "#{@param_type}".delete('!'), name, type, (@param_type['!'] ? :req : :opt), schema_hash
28
+ def _param_agent component_key, name, type = nil, **schema_info
29
+ schema = process_schema_info(type, schema_info)
30
+ return puts ' ZRO'.red + " Syntax Error: param `#{name}` has no schema type!" if schema[:illegal?]
31
+ param component_key, @param_type, name, schema[:type], @necessity, schema[:combined] || schema[:info]
39
32
  end
33
+
40
34
  arrow_enable :_param_agent
41
35
 
42
- def request_body component_key, required, media_type, data: { }, **options
43
- desc = options.delete(:desc) || ''
44
- cur = (self[:requestBodies] ||= { })[component_key]
36
+ def request_body component_key, required, media_type, data: { }, desc: '', **options
37
+ cur = self[:requestBodies][component_key]
45
38
  cur = RequestBodyObj.new(required, desc) unless cur.is_a?(RequestBodyObj)
46
39
  self[:requestBodies][component_key] = cur.add_or_fusion(media_type, { data: data, **options })
47
40
  end
48
41
 
49
42
  # [ body body! ]
50
43
  def _request_body_agent component_key, media_type, data: { }, **options
51
- request_body component_key,
52
- (@method_name['!'] ? :req : :opt), media_type, data: data, **options
44
+ request_body component_key, @necessity, media_type, data: data, **options
53
45
  end
46
+
54
47
  arrow_enable :_request_body_agent
55
48
 
56
49
  arrow_enable :resp # alias_method 竟然也会指向旧的方法?
@@ -58,8 +51,9 @@ module OpenApi
58
51
 
59
52
  def security_scheme scheme_name, other_info# = { }
60
53
  other_info[:description] = other_info.delete(:desc) if other_info[:desc]
61
- (self[:securitySchemes] ||= { })[scheme_name] = other_info
54
+ self[:securitySchemes][scheme_name] = other_info
62
55
  end
56
+
63
57
  arrow_enable :security_scheme
64
58
 
65
59
  alias auth_scheme security_scheme
@@ -67,27 +61,25 @@ module OpenApi
67
61
  def base_auth scheme_name, other_info = { }
68
62
  security_scheme scheme_name, { type: 'http', scheme: 'basic', **other_info }
69
63
  end
64
+
70
65
  arrow_enable :base_auth
71
66
 
72
67
  def bearer_auth scheme_name, format = 'JWT', other_info = { }
73
68
  security_scheme scheme_name, { type: 'http', scheme: 'bearer', bearerFormat: format, **other_info }
74
69
  end
70
+
75
71
  arrow_enable :bearer_auth
76
72
 
77
73
  def api_key scheme_name, field:, in: 'header', **other_info
78
74
  _in = binding.local_variable_get(:in)
79
75
  security_scheme scheme_name, { type: 'apiKey', name: field, in: _in, **other_info }
80
76
  end
77
+
81
78
  arrow_enable :api_key
82
79
 
83
80
  def process_objs
84
- self[:requestBodies]&.each do |key, obj|
85
- self[:requestBodies][key] = obj.process
86
- end
87
-
88
- self[:responses]&.each do |code, obj|
89
- self[:responses][code] = obj.process if obj.is_a?(ResponseObj)
90
- end
81
+ self[:requestBodies].each { |key, body| self[:requestBodies][key] = body.process }
82
+ self[:responses].each { |code, response| self[:responses][code] = response.process }
91
83
  end
92
84
  end
93
85
  end
@@ -6,11 +6,11 @@ module OpenApi
6
6
  end
7
7
 
8
8
  # :nocov:
9
- def load_schema(model)
9
+ def load_schema(model) # TODO: test
10
10
  # About `show_attrs`, see:
11
11
  # (1) BuilderSupport module: https://github.com/zhandao/zero-rails/blob/master/app/models/concerns/builder_support.rb
12
12
  # (2) config in model: https://github.com/zhandao/zero-rails/tree/master/app/models/good.rb
13
- # (3) jbuilder file: https://github.com/zhandao/zero-rails/blob/mster/app/views/api/v1/goods/index.json.jbuilder
13
+ # (3) jbuilder file: https://github.com/zhandao/zero-rails/blob/master/app/views/api/v1/goods/index.json.jbuilder
14
14
  # In a word, BuilderSupport let you control the `output fields and nested association infos` very easily.
15
15
  if model.respond_to? :show_attrs
16
16
  _load_schema_based_on_show_attr(model)
@@ -41,27 +41,43 @@ module OpenApi
41
41
  # :nocov:
42
42
 
43
43
  def fill_in_parameters(param_obj)
44
- name = param_obj.processed[:name]
45
- index = self[:parameters].map { |p| p.processed[:name] if p.is_a?(ParamObj) }.index(name)
44
+ index = self[:parameters].map(&:name).index(param_obj.name)
46
45
  index.present? ? self[:parameters][index] = param_obj : self[:parameters] << param_obj
47
46
  end
48
47
 
48
+ def _combined_schema(one_of: nil, all_of: nil, any_of: nil, not: nil, **other)
49
+ input = (_not = binding.local_variable_get(:not)) || one_of || all_of || any_of
50
+ CombinedSchema.new(one_of: one_of, all_of: all_of, any_of: any_of, _not: _not) if input
51
+ end
52
+
53
+ def process_schema_info(schema_type, schema_info, model: nil)
54
+ combined_schema = _combined_schema(schema_info)
55
+ type = schema_info[:type] ||= schema_type
56
+ schema_info = load_schema(model) if model.try(:superclass) == (Config.active_record_base || ApplicationRecord)
57
+ {
58
+ illegal?: type.nil? && combined_schema.nil?,
59
+ combined: combined_schema,
60
+ info: schema_info,
61
+ type: type
62
+ }
63
+ end
64
+
49
65
  # Arrow Writing:
50
66
  # response :RespComponent => [ '200', 'success', :json ]
51
67
  # It is equivalent to:
52
68
  # response :RespComponent, '200', 'success', :json
53
69
  # But I think, in the definition of a component,
54
- # the key-value (arrow) writing is easy to understand.
70
+ # the key-value (arrow) writing is more easier to understand.
55
71
  def arrow_writing_support
56
72
  proc do |args, executor|
57
- _args = (args.size == 1 && args.first.is_a?(Hash)) ? args[0].to_a.flatten : args
58
- send(executor, *_args)
73
+ args = (args.size == 1 && args.first.is_a?(Hash)) ? args[0].to_a.flatten : args
74
+ send(executor, *args)
59
75
  end
60
76
  end
61
77
 
62
78
  module ClassMethods
63
79
  def arrow_enable method
64
- alias_method "_#{method}".to_sym, method
80
+ alias_method :"_#{method}", method
65
81
  define_method method do |*args|
66
82
  arrow_writing_support.call(args, "_#{method}")
67
83
  end