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 +4 -4
- data/README.md +100 -19
- data/lib/oas_rails/builders/esquema_builder.rb +10 -9
- data/lib/oas_rails/oas_route.rb +5 -3
- data/lib/oas_rails/spec/media_type.rb +5 -1
- data/lib/oas_rails/utils.rb +1 -0
- data/lib/oas_rails/version.rb +1 -1
- data/lib/oas_rails/yard/oas_rails_factory.rb +8 -7
- data/lib/oas_rails.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ce2a79462161474eeb19ee711b0bdf11615c64e5695732587ebecfeef8a5c3f
|
4
|
+
data.tar.gz: 7f6df06bb7de5dffaf94019e3ba9f9bab2cc59d17b72573f69f945635b435291
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|

|
@@ -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
|
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
|
-
**
|
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
|
-
|
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
|
-
**
|
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
|
-
**
|
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
|
-
**
|
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:
|
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::
|
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:
|
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::
|
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
|
-
|
34
|
-
|
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
|
data/lib/oas_rails/oas_route.rb
CHANGED
@@ -25,9 +25,11 @@ module OasRails
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def extract_docstring
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
data/lib/oas_rails/utils.rb
CHANGED
data/lib/oas_rails/version.rb
CHANGED
@@ -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
|
-
_,
|
102
|
-
hash = eval_content(
|
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
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.
|
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-
|
11
|
+
date: 2025-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
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:
|
28
|
+
name: method_source
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
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:
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: yard
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|