oas_rails 0.12.0 → 0.13.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b929476e50a9620b4239738c1753cada50eaa6198ec363afe75dc2690f202504
4
- data.tar.gz: df7125a57463f2782254b316cd235a6b11e075e5010bc07d61e6aca8e555cd47
3
+ metadata.gz: d0b32fa577fb8e747811369e952c3508011a6270366784ab3eb0ff69d579c51b
4
+ data.tar.gz: 251e05d5a07104a8cea8635197dbf110d0749576f383aa38de6ebe7cebf89c06
5
5
  SHA512:
6
- metadata.gz: 95119f77419a24df6f3d22ef941e2dae351ad965ff2e8b84a7285a73932ab5e617d60c6c4ccfb08dfd44f555c58691ad1053b9983699d3f18b9f3c5a8a626693
7
- data.tar.gz: b4cce805735d6c2f0ba7f653bf778f59d7dd4c92be23128cac8bfd2ac0c185ccfd3b79e1f149cb1c17a0d083e8d7e83777b89f2bb96462c1acd2cfefdd6d25b9
6
+ metadata.gz: 9bcb332e43ce4caa1be24e598589a9fdba1dad280488d9c3a6b3764b0037bba2b484c525f5733bfd26fa77b76ee3f9944c88c6d6fbe3dc6649c33203d1cf9d47
7
+ data.tar.gz: 4153c860f49b50c870e3ee86382b08fa29686e96aef9f2e39056b4d4f6364617963e6d71a1e48e3bdee25ef7149548c5974986c7884c5ab6be235b642d13a8c0
@@ -26,6 +26,8 @@ OasRails.configure do |config|
26
26
 
27
27
  3. Use Yard tags in your controller methods to provide detailed API endpoint descriptions.
28
28
 
29
+ Docs: <https://a-chacon.com/oas_rails/>
30
+
29
31
  ## Features
30
32
 
31
33
  - Automatic OAS 3.1 document generation
@@ -105,6 +107,7 @@ OasRails.configure do |config|
105
107
  # Example, if you add forbidden then it will be added only if the endpoint requires authentication.
106
108
  # Example: not_found will be setted to the endpoint only if the operation is a show/update/destroy action.
107
109
  # config.set_default_responses = true
108
- # config.possible_default_responses = [:not_found, :unauthorized, :forbidden]
109
- # config.response_body_of_default = { message: String }
110
+ # config.possible_default_responses = [:not_found, :unauthorized, :forbidden, :internal_server_error, :unprocessable_entity]
111
+ # config.response_body_of_default = "Hash{ message: String }"
112
+ # config.response_body_of_unprocessable_entity= "Hash{ errors: Array<String> }"
110
113
  end
@@ -33,7 +33,7 @@ module OasRails
33
33
  end
34
34
 
35
35
  def from_model_class(klass)
36
- return self unless klass.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
36
+ return self unless Utils.active_record_class?(klass)
37
37
 
38
38
  model_schema = Builders::EsquemaBuilder.send("build_#{@context}_schema", klass:)
39
39
  model_schema["required"] = []
@@ -18,7 +18,7 @@ module OasRails
18
18
  end
19
19
 
20
20
  def from_tags(tag:, examples_tags: [])
21
- if tag.klass.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
21
+ if Utils.active_record_class?(tag.klass)
22
22
  from_model_class(klass: tag.klass, description: tag.text, required: tag.required, examples_tags:)
23
23
  else
24
24
  @request_body.description = tag.text
@@ -32,29 +32,49 @@ module OasRails
32
32
  def add_default_responses(oas_route, security)
33
33
  return self unless OasRails.config.set_default_responses
34
34
 
35
- content = ContentBuilder.new(@specification, :outgoing).with_schema(JsonSchemaGenerator.process_string(OasRails.config.response_body_of_default)[:json_schema]).build
35
+ common_errors = determine_common_errors(oas_route, security)
36
+ add_responses_for_errors(common_errors)
37
+
38
+ self
39
+ end
40
+
41
+ def build
42
+ @responses
43
+ end
44
+
45
+ private
46
+
47
+ def determine_common_errors(oas_route, security)
36
48
  common_errors = []
37
- common_errors.push(:unauthorized, :forbidden) if security
49
+ common_errors.push(:unauthorized, :forbidden, :internal_server_error) if security
38
50
 
39
51
  case oas_route.method
40
- when "show", "update", "destroy"
52
+ when "show", "destroy"
41
53
  common_errors.push(:not_found)
42
- when "create", "index"
43
- # possible errors for this methods?
54
+ when "create"
55
+ common_errors.push(:unprocessable_entity)
56
+ when "update"
57
+ common_errors.push(:not_found, :unprocessable_entity)
44
58
  end
45
59
 
46
- (OasRails.config.possible_default_responses & common_errors).each do |e|
47
- code = Utils.status_to_integer(e)
60
+ OasRails.config.possible_default_responses & common_errors
61
+ end
62
+
63
+ def add_responses_for_errors(errors)
64
+ errors.each do |error|
65
+ response_body = resolve_response_body(error)
66
+ content = ContentBuilder.new(@specification, :outgoing).with_schema(JsonSchemaGenerator.process_string(response_body)[:json_schema]).build
67
+ code = Utils.status_to_integer(error)
48
68
  response = ResponseBuilder.new(@specification).with_code(code).with_description(Utils.get_definition(code)).with_content(content).build
49
69
 
50
70
  @responses.add_response(response) if @responses.responses[response.code].blank?
51
71
  end
52
-
53
- self
54
72
  end
55
73
 
56
- def build
57
- @responses
74
+ def resolve_response_body(error)
75
+ OasRails.config.public_send("response_body_of_#{error}")
76
+ rescue StandardError
77
+ OasRails.config.response_body_of_default
58
78
  end
59
79
  end
60
80
  end
@@ -11,12 +11,11 @@ module OasRails
11
11
  :authenticate_all_routes_by_default,
12
12
  :set_default_responses,
13
13
  :possible_default_responses,
14
- :response_body_of_default,
15
14
  :http_verbs,
16
15
  :use_model_names,
17
16
  :rapidoc_theme
18
17
 
19
- attr_reader :servers, :tags, :security_schema, :include_mode
18
+ attr_reader :servers, :tags, :security_schema, :include_mode, :response_body_of_default
20
19
 
21
20
  def initialize
22
21
  @info = Spec::Info.new
@@ -33,12 +32,28 @@ module OasRails
33
32
  @security_schema = nil
34
33
  @security_schemas = {}
35
34
  @set_default_responses = true
36
- @possible_default_responses = [:not_found, :unauthorized, :forbidden]
35
+ @possible_default_responses = [:not_found, :unauthorized, :forbidden, :internal_server_error, :unprocessable_entity]
37
36
  @http_verbs = [:get, :post, :put, :patch, :delete]
38
- @response_body_of_default = "Hash{ success: !Boolean, message: String }"
37
+ @response_body_of_default = "Hash{ status: !Integer, error: String }"
39
38
  @use_model_names = false
40
39
  @rapidoc_theme = :rails
41
40
  @include_mode = :all
41
+
42
+ @possible_default_responses.each do |response|
43
+ method_name = "response_body_of_#{response}="
44
+ variable_name = "@response_body_of_#{response}"
45
+
46
+ define_singleton_method(method_name) do |value|
47
+ raise ArgumentError, "#{method_name} must be a String With a valid object" unless value.is_a?(String)
48
+
49
+ OasRails::JsonSchemaGenerator.parse_type(value)
50
+ instance_variable_set(variable_name, value)
51
+ end
52
+
53
+ define_singleton_method("response_body_of_#{response}") do
54
+ instance_variable_get(variable_name) || @response_body_of_default
55
+ end
56
+ end
42
57
  end
43
58
 
44
59
  def security_schema=(value)
@@ -73,6 +88,13 @@ module OasRails
73
88
 
74
89
  @include_mode = value
75
90
  end
91
+
92
+ def response_body_of_default=(value)
93
+ raise ArgumentError, "response_body_of_default must be a String With a valid object" unless value.is_a?(String)
94
+
95
+ OasRails::JsonSchemaGenerator.parse_type(value)
96
+ @response_body_of_default = value
97
+ end
76
98
  end
77
99
 
78
100
  DEFAULT_SECURITY_SCHEMES = {
@@ -60,7 +60,7 @@ module OasRails
60
60
  maybe_a_model, errors = content.gsub('@', "").split(".")
61
61
  klass = maybe_a_model.singularize.camelize(:upper).constantize
62
62
 
63
- if klass.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
63
+ if Utils.active_record_class?(klass)
64
64
  schema = Builders::EsquemaBuilder.build_outgoing_schema(klass:)
65
65
  if test_singularity(maybe_a_model)
66
66
  build_singular_model_schema_and_examples(maybe_a_model, errors, klass, schema)
@@ -29,6 +29,8 @@ module OasRails
29
29
  { type: :object, required:, properties: parse_object_properties(::Regexp.last_match(1)) }
30
30
  when /^Array<(.+)>$/i
31
31
  { type: :array, required:, items: parse_type(::Regexp.last_match(1)) }
32
+ when ->(t) { Utils.active_record_class?(t) }
33
+ Builders::EsquemaBuilder.build_outgoing_schema(klass: type.constantize)
32
34
  else
33
35
  { type: type.downcase.to_sym, required: }
34
36
  end
@@ -100,6 +102,8 @@ module OasRails
100
102
  type: 'array',
101
103
  items: to_json_schema(parsed[:items])
102
104
  }
105
+ when nil
106
+ parsed
103
107
  else
104
108
  ruby_type_to_json_schema_type(parsed[:type])
105
109
  end
@@ -14,6 +14,8 @@ module OasRails
14
14
  }.freeze
15
15
 
16
16
  HTTP_STATUS_DEFINITIONS = {
17
+ 200 => "The request has succeeded.",
18
+ 201 => "The request has been fulfilled and resulted in a new resource being created.",
17
19
  404 => "The requested resource could not be found.",
18
20
  401 => "You are not authorized to access this resource. You need to authenticate yourself first.",
19
21
  403 => "You are not allowed to access this resource. You do not have the necessary permissions.",
@@ -34,19 +36,6 @@ module OasRails
34
36
  end
35
37
  end
36
38
 
37
- # TODO: check if it is in use
38
- def type_to_schema(type_string)
39
- if type_string.start_with?('Array<')
40
- inner_type = type_string[/Array<(.+)>$/, 1]
41
- {
42
- "type" => "array",
43
- "items" => type_to_schema(inner_type)
44
- }
45
- else
46
- { "type" => TYPE_MAPPING.fetch(type_string, 'string') }
47
- end
48
- end
49
-
50
39
  def hash_to_json_schema(hash)
51
40
  {
52
41
  type: 'object',
@@ -116,6 +105,16 @@ module OasRails
116
105
 
117
106
  nil # Return nil if no matching constant is found
118
107
  end
108
+
109
+ # Checks if a given text refers to an ActiveRecord class.
110
+ # @param text [String] The text to check.
111
+ # @return [Boolean] True if the text refers to an ActiveRecord class, false otherwise.
112
+ def active_record_class?(klass_or_string)
113
+ klass = klass_or_string.is_a?(Class) ? klass_or_string : klass_or_string.constantize
114
+ klass.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
115
+ rescue StandardError
116
+ false
117
+ end
119
118
  end
120
119
  end
121
120
  end
@@ -1,3 +1,3 @@
1
1
  module OasRails
2
- VERSION = "0.12.0"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -147,23 +147,13 @@ module OasRails
147
147
  match
148
148
  end
149
149
 
150
- # Checks if a given text refers to an ActiveRecord class.
151
- # @param text [String] The text to check.
152
- # @return [Boolean] True if the text refers to an ActiveRecord class, false otherwise.
153
- def active_record_class?(text)
154
- klass = text.constantize
155
- klass.ancestors.map(&:to_s).include? 'ActiveRecord::Base'
156
- rescue StandardError
157
- false
158
- end
159
-
160
150
  # Converts type text to a schema, checking if it's an ActiveRecord class.
161
151
  # @param text [String] The type text to convert.
162
152
  # @return [Array] An array containing the class, schema, and required flag.
163
153
  def type_text_to_schema(text)
164
154
  type_text, required = text_and_required(text)
165
155
 
166
- if active_record_class?(type_text)
156
+ if Utils.active_record_class?(type_text)
167
157
  klass = type_text.constantize
168
158
  schema = Builders::EsquemaBuilder.build_outgoing_schema(klass:)
169
159
  else
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oas_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - a-chacon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-13 00:00:00.000000000 Z
11
+ date: 2025-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: easy_talk
14
+ name: easy_talk_two
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: 1.1.2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: 1.1.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: method_source
29
29
  requirement: !ruby/object:Gem::Requirement