oas_rails 0.9.0 → 0.10.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: 0e873607a5e36e6301251d74b2754c71d0c2b2e3591afcc7f4d3c8135be4f1c3
4
- data.tar.gz: e3f242451e51b13bc2b05b00ab9e5c440f8a139914ec567e6547fa14f8a6c09e
3
+ metadata.gz: 3ce2a79462161474eeb19ee711b0bdf11615c64e5695732587ebecfeef8a5c3f
4
+ data.tar.gz: 7f6df06bb7de5dffaf94019e3ba9f9bab2cc59d17b72573f69f945635b435291
5
5
  SHA512:
6
- metadata.gz: 66c4beb422b09cc0c801433897f892a7e52284fefbfd5598220e893d3ebdf6a026c68d54613cf4c7ab920e6cc320ba7f331ae1bc4c9dd9f4002df9d41183e79f
7
- data.tar.gz: 60faac4dfba6f28e9ac45f4c37f1879b3bd5a4136baee262ee0a950fb824128047f514cda2845623b64be3bccf5a6407234060846882f7a1033e4720a56afc52
6
+ metadata.gz: c4e58fd69b4ebc8903541e2c9bef51b435c578e18af5a05c3c63f5faf7fad11defabd35bfb4a129b4977bd034a5f432661b3d5c1f81ee6fb8462b81741f187ba
7
+ data.tar.gz: 599a61527af3f05fe535d57c7016b00a52046564b4d792c40bb9b5aa7413917d2898f36da20bf3e7064f480ab45ffcd095f9168f0865cad7397aebec3aba9256
data/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  OasRails is a Rails engine for generating **automatic interactive documentation for your Rails APIs**. It generates an **OAS 3.1** document and displays it using **[RapiDoc](https://rapidocweb.com)**.
11
11
 
12
12
  🎬 A Demo Video Here:
13
- https://vimeo.com/1013687332
13
+ <https://vimeo.com/1013687332>
14
14
  🎬
15
15
 
16
16
  ![Screenshot](https://a-chacon.com/assets/images/oas_rails_ui.png)
@@ -80,7 +80,7 @@ You'll now have **basic documentation** based on your routes and automatically g
80
80
 
81
81
  ## ⚙️ Configuration
82
82
 
83
- To configure OasRails, you MUST create an initializer file including all your settings. The first step is to create your initializer file, which you can easily do with:
83
+ To configure OasRails, **you MUST create an initializer file** including all your settings. The first step is to create your initializer file, which you can easily do with:
84
84
 
85
85
  ```bash
86
86
  rails generate oas_rails:config
@@ -135,7 +135,20 @@ In addition to the information provided in the initializer file and the data tha
135
135
 
136
136
  ### Documenting Your Endpoints
137
137
 
138
- Almost every description in an OAS file supports simple markdown. The following tags are available for documenting your endpoints:
138
+ Almost every tag description in an OAS file supports **markdown formatting** (e.g., bold, italics, lists, links) for better readability in the generated documentation. Additionally, **multi-line descriptions** are supported. When using multi-line descriptions, ensure the content is indented at least one space more than the tag itself to maintain proper formatting.
139
+
140
+ For example:
141
+
142
+ ```ruby
143
+ # @request_body_example Simple User [Hash]
144
+ # {
145
+ # user: {
146
+ # name: "Oas",
147
+ # email: "oas@test.com",
148
+ # password: "Test12345"
149
+ # }
150
+ # }
151
+ ```
139
152
 
140
153
  <details>
141
154
  <summary style="font-weight: bold; font-size: 1.2em;">@summary</summary>
@@ -145,8 +158,14 @@ Almost every description in an OAS file supports simple markdown. The following
145
158
  Used to add a summary to the endpoint. It replaces the default summary/title of the endpoint.
146
159
 
147
160
  **Example**:
161
+
148
162
  `# @summary This endpoint creates a User`
149
163
 
164
+ ```
165
+ # @summary This endpoint
166
+ # creates a User
167
+ ```
168
+
150
169
  </details>
151
170
 
152
171
  <details>
@@ -169,15 +188,31 @@ Represents a parameter for the endpoint. The position can be: `header`, `path`,
169
188
 
170
189
  Documents the request body needed by the endpoint. The structure is optional if you provide a valid Active Record class. Use `!` to indicate a required request body.
171
190
 
172
- **Example**:
173
-
174
- `# @request_body The user to be created [!Hash{user: Hash{name: String, age: Integer, password: String}}]`
191
+ **One line example**:
175
192
 
176
193
  `# @request_body The user to be created [!User]`
177
194
 
178
195
  `# @request_body The user to be created [User]`
179
196
 
180
- `# @request_body The user to be created [!Hash{user: Hash{name: String, age: Integer, password: String, surnames: Array<String>, coords: Hash{lat: String, lng: String}}}]`
197
+ **Multi-line example**:
198
+
199
+ ```ruby
200
+ # @request_body User to be created
201
+ # [
202
+ # !Hash{
203
+ # user: Hash{
204
+ # name: String,
205
+ # email: String,
206
+ # age: Integer,
207
+ # cars: Array<
208
+ # Hash{
209
+ # identifier: String
210
+ # }
211
+ # >
212
+ # }
213
+ # }
214
+ # ]
215
+ ```
181
216
 
182
217
  </details>
183
218
 
@@ -188,9 +223,23 @@ Documents the request body needed by the endpoint. The structure is optional if
188
223
 
189
224
  Adds examples to the provided request body.
190
225
 
191
- **Example**:
226
+ **One line example**:
227
+
192
228
  `# @request_body_example A complete User. [Hash] {user: {name: 'Luis', age: 30, password: 'MyWeakPassword123'}}`
193
229
 
230
+ **Multi-line example**:
231
+
232
+ ```ruby
233
+ # @request_body_example basic user [Hash]
234
+ # {
235
+ # user: {
236
+ # name: "Oas",
237
+ # email: "oas@test.com",
238
+ # password: "Test12345"
239
+ # }
240
+ # }
241
+ ```
242
+
194
243
  </details>
195
244
 
196
245
  <details>
@@ -200,12 +249,27 @@ Adds examples to the provided request body.
200
249
 
201
250
  Documents the responses of the endpoint and overrides the default responses found by the engine.
202
251
 
203
- **Example**:
252
+ **One line example**:
204
253
 
205
254
  `# @response User not found by the provided Id(404) [Hash{success: Boolean, message: String}]`
206
255
 
207
256
  `# @response Validation errors(422) [Hash{success: Boolean, errors: Array<Hash{field: String, type: String, detail: Array<String>}>}]`
208
257
 
258
+ **Multi-line example**:
259
+
260
+ ```ruby
261
+ # @response A test response from an Issue(405)
262
+ # [
263
+ # Hash{
264
+ # message: String,
265
+ # data: Hash{
266
+ # availabilities: Array<String>,
267
+ # dates: Array<Date>
268
+ # }
269
+ # }
270
+ # ]
271
+ ```
272
+
209
273
  </details>
210
274
 
211
275
  <details>
@@ -215,12 +279,27 @@ Documents the responses of the endpoint and overrides the default responses foun
215
279
 
216
280
  Documents response examples of the endpoint associated to a response code.
217
281
 
218
- **Example**:
282
+ **One line example**:
219
283
 
220
284
  `# @response_example Invalida Email(422) [{success: "false", errors: [{field: "email", type: "email", detail: ["Invalid email"]}] }]`
221
285
 
222
286
  `# @response_example Id not exists (404) [{success: "false", message: "Nothing found with the provided ID." }]`
223
287
 
288
+ **Multi-line example**:
289
+
290
+ ```ruby
291
+ # @response_example Another 405 Error (405) [Hash]
292
+ # {
293
+ # message: "another",
294
+ # data: {
295
+ # availabilities: [
296
+ # "three"
297
+ # ],
298
+ # dates: []
299
+ # }
300
+ # }
301
+ ```
302
+
224
303
  </details>
225
304
 
226
305
  <details>
@@ -282,9 +361,9 @@ class UsersController < ApplicationController
282
361
  # This method show a User by ID. The id must exist of other way it will be returning a **`404`**.
283
362
  #
284
363
  # @parameter id(path) [Integer] Used for identify the user.
285
- # @response Requested User(200) [Hash{user: {name: String, email: String, created_at: DateTime }}]
286
- # @response User not found by the provided Id(404) [Hash{success: Boolean, message: String}]
287
- # @response You don't have the right permission for access to this resource(403) [Hash{success: Boolean, message: String}]
364
+ # @response Requested User(200) [Hash] {user: {name: String, email: String, created_at: DateTime }}
365
+ # @response User not found by the provided Id(404) [Hash] {success: Boolean, message: String}
366
+ # @response You don't have the right permission for access to this resource(403) [Hash] {success: Boolean, message: String}
288
367
  def show
289
368
  render json: @user
290
369
  end
@@ -409,6 +488,8 @@ Once the custom view file is in place, Rails will automatically use it instead o
409
488
 
410
489
  Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star⭐! Thanks again!
411
490
 
491
+ If you plan a big feature, first open an issue to discuss it before any development.
492
+
412
493
  1. Fork the Project
413
494
  2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
414
495
  3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
@@ -417,14 +498,14 @@ Contributions are what make the open source community such an amazing place to l
417
498
 
418
499
  ### Roadmap and Ideas for Improvement
419
500
 
420
- - Clean, document and structure the code
501
+ - [ ] Clean, document and structure the code
421
502
  - [x] Support documentation of authentication methods
422
- - Define Global Tags/Configuration (e.g., common responses like 404 errors)
423
- - Post-process the JSON and replace common objects with references to components
424
- - Create a temporary file with the JSON in production mode to avoid rebuilding it on every request
425
- - Create tags for popular gems used in APIs (e.g., a `@pagy` tag for common pagination parameters)
503
+ - [ ] Define Global Tags/Configuration (e.g., common responses like 404 errors)
504
+ - [ ] Post-process the JSON and replace common objects with references to components
505
+ - [ ] Create a temporary file with the JSON in production mode to avoid rebuilding it on every request
506
+ - [ ] Create tags for popular gems used in APIs (e.g., a `@pagy` tag for common pagination parameters)
426
507
  - [x] Add basic authentication to OAS and UI for security reasons (Solution documented, not need to be managed by the engine)
427
- - Implement ability to define OAS by namespaces (e.g., generate OAS for specific routes like `/api` or separate versions V1 and V2)
508
+ - [ ] Implement ability to define OAS by namespaces (e.g., generate OAS for specific routes like `/api` or separate versions V1 and V2)
428
509
 
429
510
  ## License
430
511
 
@@ -6,22 +6,23 @@ module OasRails
6
6
  #
7
7
  # @param klass [Class] The class for which the schema is built.
8
8
  # @return [Hash] The schema as a JSON-compatible hash.
9
- def build_incoming_schema(klass:, model_to_schema_class: Esquema)
10
- configure_common_settings
9
+ def build_incoming_schema(klass:, model_to_schema_class: EasyTalk)
10
+ configure_common_settings(model_to_schema_class:)
11
11
  model_to_schema_class.configuration.excluded_columns = OasRails.config.excluded_columns_incoming
12
12
 
13
- model_to_schema_class::Builder.new(klass).build_schema.as_json
13
+ model_to_schema_class::ActiveRecordSchemaBuilder.new(klass).build_schema_definition.as_json["schema"]
14
14
  end
15
15
 
16
16
  # Builds a schema for a class when it is used as outgoing API data.
17
17
  #
18
18
  # @param klass [Class] The class for which the schema is built.
19
19
  # @return [Hash] The schema as a JSON-compatible hash.
20
- def build_outgoing_schema(klass:, model_to_schema_class: Esquema)
21
- configure_common_settings
20
+ def build_outgoing_schema(klass:, model_to_schema_class: EasyTalk)
21
+ configure_common_settings(model_to_schema_class:)
22
22
  model_to_schema_class.configuration.excluded_columns = OasRails.config.excluded_columns_outgoing
23
+ model_to_schema_class.configuration.exclude_primary_key = false
23
24
 
24
- model_to_schema_class::Builder.new(klass).build_schema.as_json
25
+ model_to_schema_class::ActiveRecordSchemaBuilder.new(klass).build_schema_definition.as_json["schema"]
25
26
  end
26
27
 
27
28
  private
@@ -29,9 +30,9 @@ module OasRails
29
30
  # Configures common settings for schema building.
30
31
  #
31
32
  # Excludes associations and foreign keys from the schema.
32
- def configure_common_settings
33
- Esquema.configuration.exclude_associations = true
34
- Esquema.configuration.exclude_foreign_keys = true
33
+ def configure_common_settings(model_to_schema_class: EasyTalk)
34
+ model_to_schema_class.configuration.exclude_associations = true
35
+ model_to_schema_class.configuration.exclude_foreign_keys = true
35
36
  end
36
37
  end
37
38
  end
@@ -25,9 +25,11 @@ module OasRails
25
25
  end
26
26
 
27
27
  def extract_docstring
28
- ::YARD::Docstring.parser.parse(
29
- controller_class.constantize.instance_method(method).comment.lines.map { |line| line.sub(/^#\s*/, '') }.join
30
- ).to_docstring
28
+ comment_lines = controller_class.constantize.instance_method(method).comment.lines
29
+ processed_lines = comment_lines.map do |line|
30
+ line.sub(/^# /, '')
31
+ end
32
+ ::YARD::Docstring.parser.parse(processed_lines.join).to_docstring
31
33
  end
32
34
 
33
35
  def extract_source_string
@@ -68,7 +68,11 @@ module OasRails
68
68
  def fetch_fixture_examples(klass:)
69
69
  fixture_file = Rails.root.join('test', 'fixtures', "#{klass.to_s.pluralize.downcase}.yml")
70
70
  begin
71
- fixture_data = YAML.load_file(fixture_file).with_indifferent_access
71
+ erb_result = ERB.new(File.read(fixture_file)).result
72
+ fixture_data = YAML.safe_load(
73
+ erb_result,
74
+ permitted_classes: [Symbol, ActiveSupport::HashWithIndifferentAccess]
75
+ ).with_indifferent_access
72
76
  rescue Errno::ENOENT
73
77
  return {}
74
78
  end
@@ -34,6 +34,7 @@ module OasRails
34
34
  end
35
35
  end
36
36
 
37
+ # TODO: check if it is in use
37
38
  def type_to_schema(type_string)
38
39
  if type_string.start_with?('Array<')
39
40
  inner_type = type_string[/Array<(.+)>$/, 1]
@@ -1,3 +1,3 @@
1
1
  module OasRails
2
- VERSION = "0.9.0"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -6,7 +6,7 @@ module OasRails
6
6
  # @param text [String] The tag text to parse.
7
7
  # @return [RequestBodyTag] The parsed request body tag object.
8
8
  def parse_tag_with_request_body(tag_name, text)
9
- description, klass, schema, required = extract_description_and_schema(text)
9
+ description, klass, schema, required = extract_description_and_schema(text.squish)
10
10
  RequestBodyTag.new(tag_name, description, klass, schema:, required:)
11
11
  end
12
12
 
@@ -15,7 +15,7 @@ module OasRails
15
15
  # @param text [String] The tag text to parse.
16
16
  # @return [RequestBodyExampleTag] The parsed request body example tag object.
17
17
  def parse_tag_with_request_body_example(tag_name, text)
18
- description, _, hash = extract_description_type_and_content(text, process_content: true, expresion: /^(.*?)\[([^\]]*)\](.*)$/m)
18
+ description, _, hash = extract_description_type_and_content(text.squish, process_content: true, expresion: /^(.*?)\[([^\]]*)\](.*)$/m)
19
19
  RequestBodyExampleTag.new(tag_name, description, content: hash)
20
20
  end
21
21
 
@@ -24,7 +24,8 @@ module OasRails
24
24
  # @param text [String] The tag text to parse.
25
25
  # @return [ParameterTag] The parsed parameter tag object.
26
26
  def parse_tag_with_parameter(tag_name, text)
27
- name, location, schema, required, description = extract_name_location_schema_and_description(text)
27
+ name, location, schema, required, description = extract_name_location_schema_and_description(text.squish)
28
+ name = "#{name}[]" if location == "query" && schema[:type] == "array"
28
29
  ParameterTag.new(tag_name, name, description, schema, location, required:)
29
30
  end
30
31
 
@@ -33,7 +34,7 @@ module OasRails
33
34
  # @param text [String] The tag text to parse.
34
35
  # @return [ResponseTag] The parsed response tag object.
35
36
  def parse_tag_with_response(tag_name, text)
36
- name, code, schema = extract_name_code_and_schema(text)
37
+ name, code, schema = extract_name_code_and_schema(text.squish)
37
38
  ResponseTag.new(tag_name, code, name, schema)
38
39
  end
39
40
 
@@ -42,7 +43,7 @@ module OasRails
42
43
  # @param text [String] The tag text to parse.
43
44
  # @return [ResponseExampleTag] The parsed response example tag object.
44
45
  def parse_tag_with_response_example(tag_name, text)
45
- description, code, hash = extract_name_code_and_hash(text)
46
+ description, code, hash = extract_name_code_and_hash(text.squish)
46
47
  ResponseExampleTag.new(tag_name, description, content: hash, code:)
47
48
  end
48
49
 
@@ -98,8 +99,8 @@ module OasRails
98
99
  # @return [Array] An array containing the name, code, and schema.
99
100
  def extract_name_code_and_hash(text)
100
101
  name, code = extract_text_and_parentheses_content(text)
101
- _, type, = extract_description_type_and_content(text)
102
- hash = eval_content(type)
102
+ _, _, content = extract_description_type_and_content(text, expresion: /^(.*?)\[([^\]]*)\](.*)$/m)
103
+ hash = eval_content(content)
103
104
  [name, code, hash]
104
105
  end
105
106
 
data/lib/oas_rails.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require "yard"
2
2
  require "method_source"
3
- require "esquema"
3
+ require "easy_talk"
4
4
 
5
5
  module OasRails
6
6
  require "oas_rails/version"
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oas_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.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-01-29 00:00:00.000000000 Z
11
+ date: 2025-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: method_source
14
+ name: easy_talk
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: model-to-schema
28
+ name: method_source
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.1.2
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.1.2
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: yard
43
43
  requirement: !ruby/object:Gem::Requirement