openapi_blocks 0.3.1 → 0.5.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/CHANGELOG.md +45 -4
- data/README.md +188 -85
- data/README.pt-BR.md +222 -130
- data/app/controllers/openapi_blocks/spec_controller.rb +2 -2
- data/lib/generators/openapi_blocks/install/install_generator.rb +19 -0
- data/lib/generators/openapi_blocks/install/templates/initializer.rb.tt +36 -0
- data/lib/generators/openapi_blocks/openapi/openapi_generator.rb +15 -0
- data/lib/generators/openapi_blocks/openapi/templates/openapi.rb.tt +48 -0
- data/lib/generators/openapi_blocks/serializer/serializer_generator.rb +15 -0
- data/lib/generators/openapi_blocks/serializer/templates/serializer.rb.tt +15 -0
- data/lib/openapi_blocks/auto_serialize.rb +54 -0
- data/lib/openapi_blocks/base.rb +6 -35
- data/lib/openapi_blocks/builder.rb +34 -2
- data/lib/openapi_blocks/concerns/documentable.rb +26 -0
- data/lib/openapi_blocks/concerns/schemable.rb +45 -0
- data/lib/openapi_blocks/configuration.rb +8 -1
- data/lib/openapi_blocks/controller.rb +7 -27
- data/lib/openapi_blocks/railtie.rb +14 -2
- data/lib/openapi_blocks/registry.rb +76 -0
- data/lib/openapi_blocks/serialization.rb +197 -0
- data/lib/openapi_blocks/serializer.rb +12 -182
- data/lib/openapi_blocks/spec/components.rb +6 -4
- data/lib/openapi_blocks/version.rb +1 -1
- data/lib/openapi_blocks.rb +7 -3
- metadata +17 -5
- data/lib/openapi_blocks/resource.rb +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a555c50cffdc3d57e766d1d644a2a7715ac4ab3ad730484169f86b09538d9da9
|
|
4
|
+
data.tar.gz: e55fe98e2c802e9823bef23683a8b431e97ecda4d7f6781d02995a7f5d9d1da7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 223d4851ce536c0d9cc685e5098bfe6bb3dbb9cd278ecf7f28287eab0aa6ed58fc06ecad9b1ee470f55a10843256c4e89f6c1ce298d5effadc3140597cdc375a
|
|
7
|
+
data.tar.gz: 65d27cbd44d7f8555d9fe9ad6fdf147f25e0d7e888411ba3aeef7db80ff085799d8c25d4a4dfebbfd33f0285bb3695c00af12c793609b3018f893b233e4f164d
|
data/CHANGELOG.md
CHANGED
|
@@ -7,31 +7,72 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0] - 2026-06-02
|
|
11
|
+
|
|
12
|
+
- Added generators
|
|
13
|
+
|
|
14
|
+
## [0.4.1] - 2026-06-02
|
|
15
|
+
|
|
16
|
+
- Change parallel version
|
|
17
|
+
|
|
18
|
+
## [0.4.0] - 2026-06-02
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `OpenapiBlocks::Serializer` base class for standalone serializers in `app/serializers/` — infers model from class name (e.g. `UserSerializer` -> `User`)
|
|
23
|
+
- `OpenapiBlocks::Concerns::Schemable` module extracted from `Base` — provides `model`, `ignore`, `association`, `attribute`, `serializes` DSL
|
|
24
|
+
- `OpenapiBlocks::Concerns::Documentable` module extracted from `Base` — provides `operation`, `tags` DSL
|
|
25
|
+
- `OpenapiBlocks::Serialization` module — internal serialization engine shared by `Base` and `Serializer`
|
|
26
|
+
- `OpenapiBlocks::Registry` — maps models to serializers at boot; supports convention-based (`UserSerializer` -> `User`) and explicit (`serializes User`) registration
|
|
27
|
+
- `OpenapiBlocks::AutoSerialize` — Rack middleware that intercepts `render json:` calls and applies the registered serializer automatically when `config.auto_serialize = true`
|
|
28
|
+
- `Configuration#auto_serialize` flag — opt-in automatic serialization via `config.auto_serialize = true`
|
|
29
|
+
- `Configuration#configured?` flag — set to `true` when `config.info` block is called
|
|
30
|
+
- `Builder#validate_configuration!` — raises `OpenapiBlocks::Error` with a descriptive message if `configure` was never called or `info.title`/`info.version` are blank
|
|
31
|
+
- `Railtie` now eager loads `app/serializers/**/*.rb` alongside `app/openapi/**/*.rb`
|
|
32
|
+
- `Railtie` builds `Registry` and injects `AutoSerialize` into `ActionController::Base` and `ActionController::API` when `auto_serialize` is enabled
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- `OpenapiBlocks::Resource` removed — replaced by `OpenapiBlocks::Serializer`
|
|
37
|
+
- `OpenapiBlocks::Serialization` hierarchy traversal stops at `serialization_sentinel` instead of hardcoded `OpenapiBlocks::Base`
|
|
38
|
+
- `resolve_assoc_serializer` lookup order: `PostSerializer` -> `PostOpenapi` (delegates to `_resource` if Controller) -> fallback to `as_json`
|
|
39
|
+
- `Spec::Components#build` resolves model via `resolve_schema_klass` — supports both `Controller` (via `_resource`) and `Serializer` as schema source
|
|
40
|
+
- `Base` now includes `Concerns::Schemable` and `Concerns::Documentable` — no behavioral change for existing users
|
|
41
|
+
- Supported `openapi_version` values changed to `"3.1.0"` and `"3.0.3"` (previously `"3.1"` and `"3.0"`)
|
|
42
|
+
|
|
43
|
+
### Removed
|
|
44
|
+
|
|
45
|
+
- `lib/openapi_blocks/resource.rb` — `OpenapiBlocks::Resource` is no longer part of the public API
|
|
46
|
+
|
|
10
47
|
## [0.3.1] - 2026-06-02
|
|
11
48
|
|
|
12
49
|
### Changed
|
|
50
|
+
|
|
13
51
|
- `OpenapiBlocks::Controller` now uses `controller` to specifies exact controller
|
|
14
52
|
|
|
15
53
|
## [0.3.0] - 2026-06-01
|
|
16
54
|
|
|
17
55
|
### Added
|
|
56
|
+
|
|
18
57
|
- Scalar UI served at `/docs/scalar` alongside Swagger UI
|
|
19
58
|
- `SpecController#scalar` action serving Scalar with `displayRequestDuration` and Ruby `net_http` as default client
|
|
20
|
-
|
|
59
|
+
- `Resource` and `Controller` classes to support serializer-style resources and controller-scoped OpenAPI classes (`lib/openapi_blocks/resource.rb`, `lib/openapi_blocks/controller.rb`)
|
|
21
60
|
|
|
22
61
|
### Changed
|
|
62
|
+
|
|
23
63
|
- `OpenapiBlocks::Serializer` now uses `class_eval` to compile a monolithic extractor method per serializer class at boot time, eliminating per-object branching and lambda indirection
|
|
24
64
|
- Field classification (model / virtual / association) computed once via `classify_fields` and memoized — no runtime `respond_to?` or `Array#include?` per object
|
|
25
65
|
- Association metadata indexed by name in a `Hash` for O(1) lookup instead of `Array#find` per field per object
|
|
26
66
|
- Association serializer classes resolved at compile time inside `build_assoc_method` instead of per-object via `Object.const_get`
|
|
27
67
|
- Serializer is now **1.86× faster** than the original implementation and **3.6× faster** than `as_json` across 10–5000 records with consistent linear scaling
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
68
|
+
- `Builder#openapi_classes` expanded discovery to include classes ending with `Openapi` that inherit from `OpenapiBlocks::Base` or `OpenapiBlocks::Controller` (enables controller-scoped OpenAPI classes)
|
|
69
|
+
- `Serializer` now includes virtual attributes and associations marked `read_only` in serialized output (they previously were omitted). This ensures `read_only: true` fields are present in responses/listings while still being excluded from `*Input` schemas.
|
|
70
|
+
- `Base#infer_model` updated to strip both `Openapi` and `Resource` suffixes when inferring the model class name.
|
|
31
71
|
|
|
32
72
|
## [0.2.1] - 2026-06-01
|
|
33
73
|
|
|
34
74
|
### Changed
|
|
75
|
+
|
|
35
76
|
- `association` DSL now uses `read_only: true` instead of `input: false` for consistency with `attribute` DSL
|
|
36
77
|
|
|
37
78
|
## [0.2.0] - 2026-06-01
|
data/README.md
CHANGED
|
@@ -1,21 +1,10 @@
|
|
|
1
1
|
# OpenapiBlocks
|
|
2
2
|
|
|
3
|
-
OpenapiBlocks is a Rails gem that automatically generates OpenAPI 3.0/3.1 documentation from your ActiveRecord models, ActiveModel validations, and Rails routes — inspired by
|
|
3
|
+
OpenapiBlocks is a Rails gem that automatically generates OpenAPI 3.0/3.1 documentation from your ActiveRecord models, ActiveModel validations, and Rails routes — inspired by ActiveModel::Serializer (https://github.com/rails-api/active_model_serializers).
|
|
4
4
|
|
|
5
5
|
Versão em português brasileiro: README.pt-BR.md
|
|
6
6
|
|
|
7
|
-
No manual annotation. No DSL noise in your controllers. Just declare what to expose and the spec is generated automatically. Includes a high-performance built-in serializer — ~3.6× faster than
|
|
8
|
-
|
|
9
|
-
## Key changes (recent)
|
|
10
|
-
- `OpenapiBlocks::Resource` and `OpenapiBlocks::Controller` introduced as a cleaner alternative to `OpenapiBlocks::Base` — separating serialization from documentation concerns.
|
|
11
|
-
- Default OpenAPI version is `3.1.0` (supported: `3.1.0`, `3.0.3`).
|
|
12
|
-
- Scalar UI is now served at `/docs/scalar` alongside Swagger UI at `/docs`.
|
|
13
|
-
- Swagger UI uses same-origin spec endpoints to avoid CORS issues.
|
|
14
|
-
- YAML output is normalized to use string keys so Swagger UI accepts the `openapi` version field.
|
|
15
|
-
- `association` DSL uses `read_only: true` to mark fields as response-only and exclude them from `*Input` schemas.
|
|
16
|
-
- `tags` are generated at the document root from paths and can be customized via the `tags` DSL on classes and operations.
|
|
17
|
-
- Schema references accept `Symbol` (e.g. `schema: :user`) and array items can be symbol references (e.g. `items: :user`).
|
|
18
|
-
- Serializer uses `class_eval` to compile a monolithic extractor method per class at boot — eliminating per-object branching, lambda indirection, and runtime `respond_to?` checks.
|
|
7
|
+
No manual annotation. No DSL noise in your controllers. Just declare what to expose and the spec is generated automatically. Includes a high-performance built-in serializer — ~3.6× faster than as_json with consistent linear scaling from 10 to 5000 records.
|
|
19
8
|
|
|
20
9
|
---
|
|
21
10
|
|
|
@@ -35,6 +24,70 @@ bundle install
|
|
|
35
24
|
|
|
36
25
|
---
|
|
37
26
|
|
|
27
|
+
## Generators
|
|
28
|
+
|
|
29
|
+
OpenapiBlocks provides three generators to get you started quickly.
|
|
30
|
+
|
|
31
|
+
### Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
rails generate openapi_blocks:install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Creates `config/initializers/openapi_blocks.rb` with all available options commented out, and mounts the engine in `config/routes.rb`:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
mount OpenapiBlocks::Engine => "/docs"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Openapi
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
rails generate openapi_blocks:openapi User
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Creates `app/openapi/user_openapi.rb` with all available DSL options commented out:
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
# app/openapi/user_openapi.rb
|
|
53
|
+
class UserOpenapi < OpenapiBlocks::Controller
|
|
54
|
+
# resource UserSerializer
|
|
55
|
+
# controller UsersController
|
|
56
|
+
|
|
57
|
+
# tags "Users"
|
|
58
|
+
|
|
59
|
+
# operation :index do
|
|
60
|
+
# summary "List all users"
|
|
61
|
+
# response 200, description: "List of users", schema: { type: :array, items: :User }
|
|
62
|
+
# end
|
|
63
|
+
end
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Serializer
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
rails generate openapi_blocks:serializer User
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Creates `app/serializers/user_serializer.rb` with all available DSL options commented out:
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
# app/serializers/user_serializer.rb
|
|
76
|
+
class UserSerializer < OpenapiBlocks::Serializer
|
|
77
|
+
# ignore :password_digest, :reset_password_token
|
|
78
|
+
|
|
79
|
+
# association :posts, type: :array, read_only: true
|
|
80
|
+
# association :company
|
|
81
|
+
|
|
82
|
+
# attribute :full_name, type: :string, read_only: true
|
|
83
|
+
# def full_name
|
|
84
|
+
# "#{object.first_name} #{object.last_name}"
|
|
85
|
+
# end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
38
91
|
## Setup
|
|
39
92
|
|
|
40
93
|
### 1. Mount the Engine
|
|
@@ -51,7 +104,7 @@ end
|
|
|
51
104
|
This exposes:
|
|
52
105
|
|
|
53
106
|
```
|
|
54
|
-
GET /docs -> Scalar UI
|
|
107
|
+
GET /docs -> Scalar UI (default)
|
|
55
108
|
GET /docs/swagger -> Swagger UI
|
|
56
109
|
GET /docs/openapi.json -> OpenAPI spec in JSON
|
|
57
110
|
GET /docs/openapi.yaml -> OpenAPI spec in YAML
|
|
@@ -59,14 +112,16 @@ GET /docs/openapi.yaml -> OpenAPI spec in YAML
|
|
|
59
112
|
|
|
60
113
|
### 2. Configure the initializer
|
|
61
114
|
|
|
115
|
+
OpenapiBlocks.configure is required. The gem raises OpenapiBlocks::Error on the first request if it was never called or if info.title / info.version are blank.
|
|
116
|
+
|
|
62
117
|
```ruby
|
|
63
118
|
# config/initializers/openapi_blocks.rb
|
|
64
119
|
OpenapiBlocks.configure do |config|
|
|
65
|
-
config.openapi_version = "3.1.0" # "3.0.3" or "3.1.0"
|
|
120
|
+
config.openapi_version = "3.1.0" # required — "3.0.3" or "3.1.0"
|
|
66
121
|
|
|
67
122
|
config.info do
|
|
68
|
-
title "My API"
|
|
69
|
-
version "1.0.0"
|
|
123
|
+
title "My API" # required
|
|
124
|
+
version "1.0.0" # required
|
|
70
125
|
description "API documentation generated automatically"
|
|
71
126
|
|
|
72
127
|
contact do
|
|
@@ -93,7 +148,8 @@ OpenapiBlocks.configure do |config|
|
|
|
93
148
|
end
|
|
94
149
|
end
|
|
95
150
|
|
|
96
|
-
config.watch
|
|
151
|
+
config.watch = :development # auto-reload on file changes
|
|
152
|
+
config.auto_serialize = true # optional — see Auto Serialization below
|
|
97
153
|
|
|
98
154
|
# optional: security schemes
|
|
99
155
|
config.security do
|
|
@@ -109,24 +165,25 @@ end
|
|
|
109
165
|
|
|
110
166
|
OpenapiBlocks provides two base classes with distinct responsibilities:
|
|
111
167
|
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
168
|
+
- OpenapiBlocks::Serializer — defines the model, fields, associations, and serialization logic. Lives in app/serializers/.
|
|
169
|
+
- OpenapiBlocks::Controller — defines API operations, parameters, and responses for documentation. Lives in app/openapi/.
|
|
170
|
+
- OpenapiBlocks::Base — legacy base class that combines both concerns. Still supported.
|
|
115
171
|
|
|
116
|
-
###
|
|
172
|
+
### Recommended: Serializer + Controller
|
|
117
173
|
|
|
118
174
|
```
|
|
119
175
|
app/
|
|
176
|
+
serializers/
|
|
177
|
+
user_serializer.rb -> serialization + schema
|
|
178
|
+
post_serializer.rb
|
|
120
179
|
openapi/
|
|
121
|
-
|
|
122
|
-
user_openapi.rb -> API documentation
|
|
123
|
-
post_resource.rb
|
|
180
|
+
user_openapi.rb -> API documentation
|
|
124
181
|
post_openapi.rb
|
|
125
182
|
```
|
|
126
183
|
|
|
127
184
|
```ruby
|
|
128
|
-
# app/
|
|
129
|
-
class
|
|
185
|
+
# app/serializers/user_serializer.rb
|
|
186
|
+
class UserSerializer < OpenapiBlocks::Serializer
|
|
130
187
|
# model User is inferred automatically from the class name
|
|
131
188
|
|
|
132
189
|
ignore :password_digest, :reset_password_token
|
|
@@ -137,7 +194,7 @@ class UserResource < OpenapiBlocks::Resource
|
|
|
137
194
|
attribute :access_token, type: :string, read_only: true
|
|
138
195
|
attribute :nickname, type: :string
|
|
139
196
|
|
|
140
|
-
# method defined here — called on the
|
|
197
|
+
# method defined here — called on the serializer instance
|
|
141
198
|
def full_name
|
|
142
199
|
"#{object.name} (#{object.email})"
|
|
143
200
|
end
|
|
@@ -149,7 +206,7 @@ end
|
|
|
149
206
|
```ruby
|
|
150
207
|
# app/openapi/user_openapi.rb
|
|
151
208
|
class UserOpenapi < OpenapiBlocks::Controller
|
|
152
|
-
resource
|
|
209
|
+
resource UserSerializer # links to the serializer — schema is derived from it
|
|
153
210
|
controller UsersController
|
|
154
211
|
|
|
155
212
|
tags "Users"
|
|
@@ -176,18 +233,31 @@ class UserOpenapi < OpenapiBlocks::Controller
|
|
|
176
233
|
end
|
|
177
234
|
```
|
|
178
235
|
|
|
236
|
+
#### How the OpenAPI schema is generated
|
|
237
|
+
|
|
238
|
+
When `resource UserSerializer` is declared in a `Controller`, OpenapiBlocks derives the OpenAPI schema directly from the serializer — not from the model. This guarantees that what is documented is exactly what the API returns.
|
|
239
|
+
|
|
240
|
+
The schema is built from three sources on the serializer:
|
|
241
|
+
|
|
242
|
+
- ActiveRecord columns — read from `db/schema.rb` via the inferred model. Column types are mapped to OpenAPI types automatically.
|
|
243
|
+
- `attribute` declarations — virtual fields not present in the database. Fields declared with `read_only: true` appear in the `User` response schema but are excluded from the `UserInput` request schema.
|
|
244
|
+
- `association` declarations — resolved as `$ref` to the associated schema. Associations declared with `read_only: true` appear in the response but are excluded from `UserInput`.
|
|
245
|
+
- `ignore` declarations — columns excluded from both schemas.
|
|
246
|
+
|
|
247
|
+
The `UserInput` schema (used in POST, PUT and PATCH request bodies) is derived automatically from the `User` schema by removing `id`, `created_at`, `updated_at`, and any field marked `read_only: true`.
|
|
248
|
+
|
|
179
249
|
```ruby
|
|
180
250
|
# app/controllers/users_controller.rb
|
|
181
251
|
def index
|
|
182
|
-
render json:
|
|
252
|
+
render json: UserSerializer.serialize(User.includes(:posts))
|
|
183
253
|
end
|
|
184
254
|
|
|
185
255
|
def show
|
|
186
|
-
render json:
|
|
256
|
+
render json: UserSerializer.serialize(User.find(params[:id]))
|
|
187
257
|
end
|
|
188
258
|
```
|
|
189
259
|
|
|
190
|
-
### Base (
|
|
260
|
+
### Legacy: Base (single class)
|
|
191
261
|
|
|
192
262
|
```ruby
|
|
193
263
|
# app/openapi/user_openapi.rb
|
|
@@ -216,36 +286,68 @@ end
|
|
|
216
286
|
|
|
217
287
|
---
|
|
218
288
|
|
|
289
|
+
## Auto Serialization
|
|
290
|
+
|
|
291
|
+
When `config.auto_serialize = true`, OpenapiBlocks intercepts every `render json:` call and automatically applies the registered serializer — no explicit serializer call needed in controllers.
|
|
292
|
+
|
|
293
|
+
```ruby
|
|
294
|
+
# config/initializers/openapi_blocks.rb
|
|
295
|
+
config.auto_serialize = true
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
# app/controllers/users_controller.rb
|
|
300
|
+
def index
|
|
301
|
+
render json: User.all # automatically serialized by UserSerializer
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def show
|
|
305
|
+
render json: @user # automatically serialized by UserSerializer
|
|
306
|
+
end
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Serializer registration is automatic by convention (UserSerializer -> User). For explicit registration:
|
|
310
|
+
|
|
311
|
+
```ruby
|
|
312
|
+
class AdminUserSerializer < OpenapiBlocks::Serializer
|
|
313
|
+
serializes User # explicitly maps this serializer to the User model
|
|
314
|
+
end
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
If no serializer is found, OpenapiBlocks falls back to default Rails rendering and logs a warning.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
219
321
|
## Serializer
|
|
220
322
|
|
|
221
|
-
The built-in serializer compiles a monolithic extractor method per class at boot time using
|
|
323
|
+
The built-in serializer compiles a monolithic extractor method per class at boot time using class_eval. There are no loops, no lambda indirection, and no runtime branching per object.
|
|
222
324
|
|
|
223
325
|
### Performance (200 records, arm64, Ruby 4.0)
|
|
224
326
|
|
|
225
|
-
| | i/s
|
|
226
|
-
|
|
227
|
-
| serialize
|
|
228
|
-
| to_json
|
|
229
|
-
| as_json
|
|
230
|
-
| oj+as_json | 1 126 | 888
|
|
327
|
+
| Method | i/s | us/i | vs serialize |
|
|
328
|
+
| ---------- | ----- | ---- | ------------ |
|
|
329
|
+
| serialize | 4 239 | 235 | — |
|
|
330
|
+
| to_json | 1 444 | 692 | 2.94x slower |
|
|
331
|
+
| as_json | 1 186 | 843 | 3.58x slower |
|
|
332
|
+
| oj+as_json | 1 126 | 888 | 3.77x slower |
|
|
231
333
|
|
|
232
|
-
Scaling is linear — the 3.
|
|
334
|
+
Scaling is linear — the 3.6x advantage over as_json holds from 10 to 5000 records.
|
|
233
335
|
|
|
234
336
|
### Virtual attributes and method resolution
|
|
235
337
|
|
|
236
|
-
| Declared with
|
|
237
|
-
|
|
238
|
-
|
|
|
239
|
-
|
|
|
240
|
-
| column in db
|
|
338
|
+
| Declared with | Method in serializer? | Calls |
|
|
339
|
+
| -------------------- | --------------------- | ------------------------------------- |
|
|
340
|
+
| attribute :full_name | yes | serializer_instance.full_name |
|
|
341
|
+
| attribute :full_name | no | object.full_name (delegated to model) |
|
|
342
|
+
| column in db | — | object.attribute (direct) |
|
|
241
343
|
|
|
242
344
|
### Association serializer resolution
|
|
243
345
|
|
|
244
346
|
For each association, the serializer resolves the serializer class in this order:
|
|
245
347
|
|
|
246
|
-
1.
|
|
247
|
-
2.
|
|
248
|
-
3. Fallback — calls
|
|
348
|
+
1. PostSerializer — has serialize, used directly.
|
|
349
|
+
2. PostOpenapi — is a Controller, delegates to its resource.
|
|
350
|
+
3. Fallback — calls as_json on the association value.
|
|
249
351
|
|
|
250
352
|
---
|
|
251
353
|
|
|
@@ -264,14 +366,14 @@ end
|
|
|
264
366
|
|
|
265
367
|
OpenapiBlocks generates:
|
|
266
368
|
|
|
267
|
-
-
|
|
268
|
-
-
|
|
269
|
-
-
|
|
270
|
-
-
|
|
271
|
-
-
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
- All paths from
|
|
369
|
+
- User schema from db/schema.rb columns and types
|
|
370
|
+
- UserInput schema for POST, PUT and PATCH request bodies (without id, created_at, updated_at and read_only fields)
|
|
371
|
+
- required fields from presence: true validations
|
|
372
|
+
- minLength, maxLength from length validations
|
|
373
|
+
- minimum, maximum from numericality validations
|
|
374
|
+
- enum from inclusion validations
|
|
375
|
+
- format: "email" from format validations
|
|
376
|
+
- All paths from config/routes.rb
|
|
275
377
|
|
|
276
378
|
---
|
|
277
379
|
|
|
@@ -281,8 +383,8 @@ Configure global security schemes in the initializer:
|
|
|
281
383
|
|
|
282
384
|
```ruby
|
|
283
385
|
config.security do
|
|
284
|
-
bearer_token format: "JWT"
|
|
285
|
-
api_key name: "X-API-Key", in: :header
|
|
386
|
+
bearer_token format: "JWT" # Authorization: Bearer <token>
|
|
387
|
+
api_key name: "X-API-Key", in: :header # X-API-Key: <key>
|
|
286
388
|
end
|
|
287
389
|
```
|
|
288
390
|
|
|
@@ -290,11 +392,11 @@ Override security per operation:
|
|
|
290
392
|
|
|
291
393
|
```ruby
|
|
292
394
|
operation :index do
|
|
293
|
-
security :bearerAuth
|
|
395
|
+
security :bearerAuth # only bearer on this operation
|
|
294
396
|
end
|
|
295
397
|
|
|
296
398
|
operation :show do
|
|
297
|
-
no_security!
|
|
399
|
+
no_security! # public endpoint — no auth required
|
|
298
400
|
end
|
|
299
401
|
```
|
|
300
402
|
|
|
@@ -303,9 +405,9 @@ end
|
|
|
303
405
|
## Associations
|
|
304
406
|
|
|
305
407
|
```ruby
|
|
306
|
-
association :company
|
|
307
|
-
association :posts, type: :array
|
|
308
|
-
association :posts, type: :array, read_only: true
|
|
408
|
+
association :company # belongs_to — $ref to Company schema
|
|
409
|
+
association :posts, type: :array # has_many — array of $ref to Post schema
|
|
410
|
+
association :posts, type: :array, read_only: true # excluded from UserInput (response only)
|
|
309
411
|
```
|
|
310
412
|
|
|
311
413
|
---
|
|
@@ -314,34 +416,34 @@ association :posts, type: :array, read_only: true # excluded from UserInput
|
|
|
314
416
|
|
|
315
417
|
Virtual attributes are fields that exist in the API response but not in the database.
|
|
316
418
|
|
|
317
|
-
| Option
|
|
318
|
-
|
|
319
|
-
|
|
|
320
|
-
|
|
|
419
|
+
| Option | Description | Appears in User | Appears in UserInput |
|
|
420
|
+
| ---------------- | -------------------------------------- | :-------------: | :------------------: |
|
|
421
|
+
| read_only: true | Calculated or system-generated fields | YES | NO |
|
|
422
|
+
| read_only: false | Fields the client can send and receive | YES | YES |
|
|
321
423
|
|
|
322
424
|
```ruby
|
|
323
|
-
attribute :full_name, type: :string, read_only: true
|
|
324
|
-
attribute :access_token, type: :string, read_only: true
|
|
325
|
-
attribute :nickname, type: :string
|
|
425
|
+
attribute :full_name, type: :string, read_only: true # response only
|
|
426
|
+
attribute :access_token, type: :string, read_only: true # response only
|
|
427
|
+
attribute :nickname, type: :string # request and response
|
|
326
428
|
```
|
|
327
429
|
|
|
328
430
|
---
|
|
329
431
|
|
|
330
432
|
## Type Mapping
|
|
331
433
|
|
|
332
|
-
| ActiveRecord type | OpenAPI type
|
|
333
|
-
|
|
334
|
-
| integer
|
|
335
|
-
| bigint
|
|
336
|
-
| float
|
|
337
|
-
| decimal
|
|
338
|
-
| string
|
|
339
|
-
| text
|
|
340
|
-
| boolean
|
|
341
|
-
| date
|
|
342
|
-
| datetime
|
|
343
|
-
| uuid
|
|
344
|
-
| json / jsonb
|
|
434
|
+
| ActiveRecord type | OpenAPI type |
|
|
435
|
+
| ----------------- | ------------------ |
|
|
436
|
+
| integer | integer / int32 |
|
|
437
|
+
| bigint | integer / int64 |
|
|
438
|
+
| float | number / float |
|
|
439
|
+
| decimal | number / double |
|
|
440
|
+
| string | string |
|
|
441
|
+
| text | string |
|
|
442
|
+
| boolean | boolean |
|
|
443
|
+
| date | string / date |
|
|
444
|
+
| datetime | string / date-time |
|
|
445
|
+
| uuid | string / uuid |
|
|
446
|
+
| json / jsonb | object |
|
|
345
447
|
|
|
346
448
|
---
|
|
347
449
|
|
|
@@ -350,13 +452,14 @@ attribute :nickname, type: :string # request and response
|
|
|
350
452
|
OpenapiBlocks watches for changes in:
|
|
351
453
|
|
|
352
454
|
```
|
|
455
|
+
app/serializers/**/*.rb
|
|
353
456
|
app/openapi/**/*.rb
|
|
354
457
|
app/models/**/*.rb
|
|
355
458
|
config/routes.rb
|
|
356
459
|
db/schema.rb
|
|
357
460
|
```
|
|
358
461
|
|
|
359
|
-
The spec is automatically regenerated on the next request to
|
|
462
|
+
The spec is automatically regenerated on the next request to /docs/openapi.json whenever any of these files change. No server restart needed.
|
|
360
463
|
|
|
361
464
|
---
|
|
362
465
|
|
|
@@ -369,4 +472,4 @@ The spec is automatically regenerated on the next request to `/docs/openapi.json
|
|
|
369
472
|
|
|
370
473
|
## License
|
|
371
474
|
|
|
372
|
-
MIT (LICENSE.txt)
|
|
475
|
+
MIT (LICENSE.txt)
|