jbuilder-schema 2.6.7 → 2.6.9
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 +228 -118
- data/lib/jbuilder/schema/template.rb +51 -26
- data/lib/jbuilder/schema/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dc6b74ad43767a8a12d27263b224beb94b8a3aa4deab865e81fb2753ff367718
|
|
4
|
+
data.tar.gz: 03243e798c0e28991c926b52b90d448b79d7f66aa0f59b997d9fd384b5d4bd28
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aaa65e842309918131ba5ae7f01f2063dcd9312505d9677a1037bab01801b8eab1865b8cd00daeca3712cbf367dd5494526939468623b4b1af706c86ac6c5751
|
|
7
|
+
data.tar.gz: a12318b8132a8a6edca71fcfe746dc6a757afe7a105405c17ca9ba22683ad7ebd51c4978bad692ab90c81f14d242ebf0dba016d6ff4e9fc039cc9b816ed007e5
|
data/README.md
CHANGED
|
@@ -1,62 +1,58 @@
|
|
|
1
1
|
# Jbuilder::Schema
|
|
2
2
|
|
|
3
|
-
Generate
|
|
3
|
+
Easily Generate OpenAPI 3.1 Schemas from Jbuilder Templates
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### Installation
|
|
8
|
+
|
|
9
|
+
Add this to your Gemfile:
|
|
8
10
|
|
|
9
11
|
gem "jbuilder"
|
|
10
12
|
gem "jbuilder-schema"
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
$ bundle
|
|
15
|
-
|
|
16
|
-
Or install it yourself as:
|
|
14
|
+
Then, run `bundle` or install it manually using `gem install jbuilder-schema`.
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
### Generating Schemas
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Wherever you want to generate schemas, call `Jbuilder::Schema.yaml` or `Jbuilder::Schema.json`:
|
|
18
|
+
Use `Jbuilder::Schema.yaml` or `Jbuilder::Schema.json` to create schemas. For example:
|
|
23
19
|
|
|
24
20
|
```ruby
|
|
25
21
|
Jbuilder::Schema.yaml(@article, title: 'Article', description: 'Article in the blog', locals: { current_user: @user })
|
|
26
22
|
```
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
This will render a Jbuilder template (e.g., `articles/_article.json.jbuilder`) and make `@article` available in the partial. You can also pass additional locals.
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
## Contents
|
|
31
27
|
|
|
32
|
-
|
|
28
|
+
- [Advanced Usage](#advanced-usage)
|
|
29
|
+
- [Rendering Specific Directories](#rendering-specific-directories)
|
|
30
|
+
- [Rendering Templates](#rendering-templates)
|
|
31
|
+
- [Output](#output)
|
|
32
|
+
- [Handling Arrays and Objects](#handling-arrays-and-objects)
|
|
33
|
+
- [Nested Partials and Arrays](#nested-partials-and-arrays)
|
|
34
|
+
- [Customization](#customization)
|
|
35
|
+
- [Titles & Descriptions](#titles--descriptions)
|
|
36
|
+
- [Configuration](#configuration)
|
|
37
|
+
- [Integration with RSwag](#integration-with-rswag)
|
|
38
|
+
- [Contributing](#contributing)
|
|
39
|
+
- [License](#license)
|
|
40
|
+
- [Sponsor](#open-source-development-sponsored-by)
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
### Advanced Usage
|
|
35
43
|
|
|
36
|
-
|
|
44
|
+
#### Rendering Specific Directories
|
|
37
45
|
|
|
38
|
-
If
|
|
46
|
+
If your Jbuilder templates are in a specific directory, use `Jbuilder::Schema.renderer`:
|
|
39
47
|
|
|
40
48
|
```ruby
|
|
41
49
|
jbuilder = Jbuilder::Schema.renderer('app/views/api/v1', locals: { current_user: @user })
|
|
42
50
|
jbuilder.yaml @article, title: 'Article', description: 'Article in the blog'
|
|
43
51
|
```
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
#### Rendering Templates
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
Jbuilder::Schema.yaml(partial: 'api/v1/articles/article', locals: { article: @article, current_user: @user }, title: 'Article', description: 'Article in the blog')
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Rendering a template
|
|
52
|
-
|
|
53
|
-
If you're rendering a template like `app/views/articles/index.jbuilder`:
|
|
54
|
-
|
|
55
|
-
```ruby
|
|
56
|
-
json.articles @articles, :id, :title
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
You'll need to pass the relative template path in `template:` and any needed instance variables in `assigns:` like so:
|
|
55
|
+
For templates like `app/views/articles/index.jbuilder`, specify the template path and variables:
|
|
60
56
|
|
|
61
57
|
```ruby
|
|
62
58
|
Jbuilder::Schema.yaml(template: "articles/index", assigns: { articles: Article.first(3) })
|
|
@@ -64,15 +60,16 @@ Jbuilder::Schema.yaml(template: "articles/index", assigns: { articles: Article.f
|
|
|
64
60
|
|
|
65
61
|
### Output
|
|
66
62
|
|
|
67
|
-
Jbuilder::Schema automatically sets `description`, `type`, and `required`
|
|
63
|
+
Jbuilder::Schema automatically sets `description`, `type`, and `required` fields in the JSON Schema. You can *[customize](#customization)* these using the `schema:` hash.
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
#### Example
|
|
70
66
|
|
|
71
67
|
```ruby
|
|
68
|
+
# _article.json.jbuilder
|
|
72
69
|
json.extract! article, :id, :title, :body, :created_at
|
|
73
70
|
```
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
#### Result
|
|
76
73
|
|
|
77
74
|
```yaml
|
|
78
75
|
type: object
|
|
@@ -84,148 +81,261 @@ required:
|
|
|
84
81
|
- body
|
|
85
82
|
properties:
|
|
86
83
|
id:
|
|
87
|
-
description: ID of an article
|
|
88
84
|
type: integer
|
|
85
|
+
description: Article ID
|
|
89
86
|
title:
|
|
90
|
-
description: Title of an article
|
|
91
87
|
type: string
|
|
88
|
+
description: Article Title
|
|
92
89
|
body:
|
|
93
|
-
description: Contents of an article
|
|
94
90
|
type: string
|
|
91
|
+
description: Article Contents
|
|
95
92
|
created_at:
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
type:
|
|
94
|
+
- string
|
|
95
|
+
- "null"
|
|
98
96
|
format: date-time
|
|
97
|
+
description: Timestamp when article was created
|
|
99
98
|
```
|
|
100
99
|
|
|
101
|
-
###
|
|
100
|
+
### Handling Arrays and Objects
|
|
101
|
+
|
|
102
|
+
The gem efficiently handles arrays and objects, including nested structures. Arrays with a single element type are straightforwardly represented, while arrays with mixed types use the `anyOf` keyword for versatility.
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
Support of various object types like `Hash`, `Struct`, `OpenStruct`, and `ActiveRecord::Base` is also integrated. It simplifies object schemas by setting only `type` and `properties`.
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
#### Example
|
|
106
107
|
|
|
107
108
|
```ruby
|
|
108
|
-
json.
|
|
109
|
-
json.title article.title, schema: { minLength: 5, maxLength: 20 }
|
|
110
|
-
json.body article.body, schema: { type: :text, maxLength: 500 }
|
|
111
|
-
json.created_at article.created_at.strftime('%d/%m/%Y'), schema: { format: :date, pattern: /^(3[01]|[12][0-9]|0[1-9])\/(1[0-2]|0[1-9])\/[0-9]{4}$/ }
|
|
109
|
+
json.custom_array [1, article.user, 2, "Text", [3.14, 25.44], 5.33, [3, "Another text", {a: 4, b: "One more text"}], {c: 5, d: "And another"}, {e: 6, f: {g: 7, h: "Last Text"}}]
|
|
112
110
|
```
|
|
113
111
|
|
|
114
|
-
|
|
112
|
+
#### Result
|
|
115
113
|
|
|
116
114
|
```yaml
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
115
|
+
properties:
|
|
116
|
+
custom_array:
|
|
117
|
+
type:
|
|
118
|
+
- array
|
|
119
|
+
- "null"
|
|
120
|
+
minContains: 0
|
|
121
|
+
contains:
|
|
122
|
+
anyOf:
|
|
123
|
+
- type: integer
|
|
124
|
+
- type: object
|
|
125
|
+
# ... ActiveRecord object properties ...
|
|
126
|
+
- type: string
|
|
127
|
+
- type: array
|
|
128
|
+
# All arrays are merged in one so all possible values of arrays are in one place
|
|
129
|
+
minContains: 0
|
|
130
|
+
contains:
|
|
131
|
+
anyOf:
|
|
132
|
+
- type: number
|
|
133
|
+
- type: integer
|
|
134
|
+
- type: string
|
|
135
|
+
- type: object
|
|
136
|
+
properties:
|
|
137
|
+
a:
|
|
138
|
+
type: integer
|
|
139
|
+
# ... description ...
|
|
140
|
+
b:
|
|
141
|
+
type: integer
|
|
142
|
+
# ... description ...
|
|
143
|
+
- type: number
|
|
144
|
+
- type: object
|
|
145
|
+
properties:
|
|
146
|
+
c:
|
|
147
|
+
type: integer
|
|
148
|
+
# ... description ...
|
|
149
|
+
d:
|
|
150
|
+
type: integer
|
|
151
|
+
# ... description ...
|
|
152
|
+
- type: object
|
|
153
|
+
properties:
|
|
154
|
+
e:
|
|
155
|
+
type: integer
|
|
156
|
+
# ... description ...
|
|
157
|
+
f:
|
|
158
|
+
type: object
|
|
159
|
+
properties:
|
|
160
|
+
h:
|
|
161
|
+
type: integer
|
|
162
|
+
# ... description ...
|
|
163
|
+
g:
|
|
164
|
+
type: string
|
|
165
|
+
# ... description ...
|
|
166
|
+
description: Very weird custom array
|
|
136
167
|
```
|
|
137
168
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
You can customize output for multiple fields at once:
|
|
169
|
+
Each schema is unique, ensuring no duplication. Description fields are nested under parent field names for clarity.
|
|
141
170
|
|
|
142
|
-
|
|
143
|
-
json.extract! user, :id, :name, :email, schema: {id: {type: :string}, email: {type: :email, pattern: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/}}
|
|
144
|
-
```
|
|
171
|
+
### Nested Partials and Arrays
|
|
145
172
|
|
|
146
|
-
|
|
173
|
+
Nested partials and arrays will most commonly produce reference to the related schema component.
|
|
174
|
+
Only if block with partial includes other fields, the inline object will be generated.
|
|
147
175
|
|
|
148
|
-
|
|
176
|
+
#### Example
|
|
149
177
|
|
|
150
178
|
```ruby
|
|
151
|
-
json.
|
|
152
|
-
json.
|
|
153
|
-
|
|
179
|
+
json.author do
|
|
180
|
+
json.partial! "api/v1/users/user", user: article.user
|
|
181
|
+
end
|
|
182
|
+
json.comments do
|
|
183
|
+
json.array! article.comments, partial: "api/v1/articles/comments/comment", as: :article_comment
|
|
184
|
+
end
|
|
185
|
+
json.ratings do
|
|
186
|
+
json.array! article.ratings, schema: {object: article.ratings.first, title: "Rating", description: "Article Rating"} do |rating|
|
|
187
|
+
json.partial! "api/v1/shared/id", resource: rating
|
|
188
|
+
json.extract! rating, :value
|
|
189
|
+
end
|
|
154
190
|
end
|
|
155
191
|
```
|
|
156
192
|
|
|
157
|
-
|
|
193
|
+
#### Result
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
# ... object description ...
|
|
197
|
+
properties:
|
|
198
|
+
author:
|
|
199
|
+
type: object
|
|
200
|
+
allOf:
|
|
201
|
+
- "$ref": "#/components/schemas/User"
|
|
202
|
+
description: User
|
|
203
|
+
comments:
|
|
204
|
+
type: array
|
|
205
|
+
items:
|
|
206
|
+
- "$ref": "#/components/schemas/Comment"
|
|
207
|
+
description: Comments
|
|
208
|
+
ratings:
|
|
209
|
+
type: array
|
|
210
|
+
items:
|
|
211
|
+
type: object
|
|
212
|
+
title: Rating
|
|
213
|
+
description: Article Rating
|
|
214
|
+
required:
|
|
215
|
+
- id
|
|
216
|
+
- value
|
|
217
|
+
properties:
|
|
218
|
+
id:
|
|
219
|
+
type: integer
|
|
220
|
+
description: Rating ID
|
|
221
|
+
public_id:
|
|
222
|
+
type:
|
|
223
|
+
- string
|
|
224
|
+
- "null"
|
|
225
|
+
description: Rating Public ID
|
|
226
|
+
value:
|
|
227
|
+
type: integer
|
|
228
|
+
description: Rating Value
|
|
229
|
+
description: Article Ratings
|
|
230
|
+
```
|
|
158
231
|
|
|
159
|
-
|
|
232
|
+
Reference names are taken from `:as` option or first of the `locals:`.
|
|
160
233
|
|
|
161
|
-
|
|
234
|
+
The path to component schemas can be configured with `components_path` variable, which defaults to `components/schemas`. See *[Configuration](#configuration)* for more info.
|
|
162
235
|
|
|
163
|
-
|
|
236
|
+
### Customization
|
|
237
|
+
|
|
238
|
+
Customize individual or multiple fields at once using the `schema:` attribute.
|
|
239
|
+
For nested objects and collections, use the `schema: {object: <nested_object>}` format.
|
|
240
|
+
|
|
241
|
+
#### Example
|
|
164
242
|
|
|
165
243
|
```ruby
|
|
166
|
-
json.
|
|
167
|
-
|
|
168
|
-
|
|
244
|
+
json.id article.id, schema: { type: :number, description: "Custom ID description" }
|
|
245
|
+
json.title article.title, schema: { minLength: 5, maxLength: 20 }
|
|
246
|
+
json.contents article.body, schema: { type: :text, maxLength: 500, required: true }
|
|
247
|
+
json.created_at article.created_at.strftime('%d/%m/%Y'), schema: { format: :date, pattern: /^(3[01]|[12][0-9]|0[1-9])\/(1[0-2]|0[1-9])\/[0-9]{4}$/ }
|
|
169
248
|
|
|
170
|
-
json.
|
|
171
|
-
json.
|
|
249
|
+
json.author schema: {object: article.user, title: "Article Author", description: "The person who wrote the article", required: true} do
|
|
250
|
+
json.extract! article.user, :id, :name, :email, schema: {id: {type: :string}, email: {type: :email, pattern: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/}}
|
|
172
251
|
end
|
|
173
252
|
```
|
|
174
253
|
|
|
175
|
-
|
|
254
|
+
#### Result
|
|
176
255
|
|
|
177
256
|
```yaml
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
257
|
+
type: object
|
|
258
|
+
title: Article
|
|
259
|
+
description: Article in the blog
|
|
260
|
+
required:
|
|
261
|
+
- id
|
|
262
|
+
- title
|
|
263
|
+
- contents
|
|
264
|
+
- author
|
|
265
|
+
properties:
|
|
266
|
+
id:
|
|
267
|
+
type: number
|
|
268
|
+
description: Custom ID description
|
|
269
|
+
title:
|
|
270
|
+
type: string
|
|
271
|
+
minLength: 5
|
|
272
|
+
maxLength: 20
|
|
273
|
+
description: Title of an article
|
|
274
|
+
contents:
|
|
275
|
+
type: string
|
|
276
|
+
maxLength: 500
|
|
277
|
+
description: Contents of an article
|
|
278
|
+
created_at:
|
|
279
|
+
type:
|
|
280
|
+
- string
|
|
281
|
+
- "null"
|
|
282
|
+
format: date
|
|
283
|
+
pattern: "^(3[01]|[12][0-9]|0[1-9])\/(1[0-2]|0[1-9])\/[0-9]{4}$"
|
|
284
|
+
description: Timestamp when article was created
|
|
285
|
+
author:
|
|
286
|
+
type: object
|
|
287
|
+
title: Article Author
|
|
288
|
+
description: The person who wrote the article
|
|
289
|
+
required:
|
|
290
|
+
- id
|
|
291
|
+
- name
|
|
292
|
+
- email
|
|
293
|
+
properties:
|
|
294
|
+
id:
|
|
295
|
+
type: string
|
|
296
|
+
description: User ID
|
|
297
|
+
name:
|
|
298
|
+
type: string
|
|
299
|
+
description: User Name
|
|
300
|
+
email:
|
|
301
|
+
type: email
|
|
302
|
+
pattern: "^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"
|
|
303
|
+
description: User Email
|
|
185
304
|
```
|
|
186
305
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
### Titles & Descriptions
|
|
306
|
+
#### Titles & Descriptions
|
|
190
307
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Titles and descriptions for the models are supposed to be found in locale files under `<underscored_plural_model_name>.<title_name>` and `<underscored_plural_model_name>.<description_name>`, for example:
|
|
308
|
+
Set custom titles and descriptions directly or through locale files. For models, use `<underscored_plural_model_name>.<title_name>` and for fields, use `<underscored_plural_model_name>.fields.<field_name>.<description_name>` in locale files:
|
|
194
309
|
|
|
195
310
|
```yaml
|
|
196
311
|
en:
|
|
197
312
|
articles:
|
|
198
313
|
title: Article
|
|
199
314
|
description: The main object on the blog
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Descriptions for the fields are supposed to be found in locale files under `<underscored_plural_model_name>.fields.<field_name>.<description_name>`, for example:
|
|
203
|
-
|
|
204
|
-
```yaml
|
|
205
|
-
en:
|
|
206
|
-
articles:
|
|
207
315
|
fields:
|
|
208
316
|
title:
|
|
209
317
|
description: The title of an article
|
|
210
318
|
```
|
|
211
319
|
|
|
212
|
-
`<title_name>` and `<description_name>` can be configured (see *[Configuration](#configuration)*), it defaults to `title` and `description`.
|
|
213
|
-
|
|
214
320
|
### Configuration
|
|
215
321
|
|
|
216
|
-
|
|
322
|
+
Configure Jbuilder::Schema in `config/initializers/jbuilder_schema.rb`:
|
|
323
|
+
|
|
324
|
+
The `title_name` and `description_name` parameters can accept either a single string or an array of strings. This feature provides the flexibility to specify fallback keys.
|
|
217
325
|
|
|
218
326
|
```ruby
|
|
219
327
|
Jbuilder::Schema.configure do |config|
|
|
220
|
-
config.components_path = "components/schemas"
|
|
221
|
-
config.title_name = "title"
|
|
222
|
-
config.description_name =
|
|
328
|
+
config.components_path = "components/schemas" # could be "definitions/schemas"
|
|
329
|
+
config.title_name = "title" # could be "label", or an array to support fallbacks, like
|
|
330
|
+
config.description_name = %w[api_description description] # could be just string as well like "heading"
|
|
223
331
|
end
|
|
224
332
|
```
|
|
225
333
|
|
|
226
|
-
|
|
334
|
+
With this configuration, the system will first try to find a translation for <underscored_plural_model_name>.fields.<field_name>.api_description. If it doesn't find a translation for this key, it will then attempt to find a translation for <underscored_plural_model_name>.fields.<field_name>.description.
|
|
335
|
+
|
|
336
|
+
### Integration with RSwag
|
|
227
337
|
|
|
228
|
-
|
|
338
|
+
Use `yaml`/`json` methods in your `swagger_helper.rb` for Swagger documentation:
|
|
229
339
|
|
|
230
340
|
```ruby
|
|
231
341
|
RSpec.configure do |config|
|
|
@@ -246,11 +356,11 @@ end
|
|
|
246
356
|
|
|
247
357
|
## Contributing
|
|
248
358
|
|
|
249
|
-
|
|
359
|
+
Contributions are welcome! Report bugs and submit pull requests on [GitHub](https://github.com/bullet-train-co/jbuilder-schema).
|
|
250
360
|
|
|
251
361
|
## License
|
|
252
362
|
|
|
253
|
-
|
|
363
|
+
This gem is open source under the [MIT License](https://opensource.org/licenses/MIT).
|
|
254
364
|
|
|
255
365
|
## Open-source development sponsored by:
|
|
256
366
|
|
|
@@ -30,21 +30,39 @@ class Jbuilder::Schema
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def title
|
|
33
|
-
super || translate(
|
|
33
|
+
super || translate(title_keys)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def description
|
|
37
|
-
super || translate(
|
|
37
|
+
super || translate(description_keys)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
def
|
|
41
|
-
translate("fields.#{key}.#{
|
|
40
|
+
def translate_title(key)
|
|
41
|
+
translate(title_keys.map { |k| "fields.#{key}.#{k}" })
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def translate_description(key)
|
|
45
|
+
translate(description_keys.map { |k| "fields.#{key}.#{k}" })
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
private
|
|
45
49
|
|
|
46
|
-
def translate(
|
|
47
|
-
|
|
50
|
+
def translate(keys)
|
|
51
|
+
keys.each do |key|
|
|
52
|
+
translation = I18n.t(key, scope: @scope ||= object&.class&.name&.underscore&.pluralize, default: nil)
|
|
53
|
+
return translation if translation.present?
|
|
54
|
+
end
|
|
55
|
+
# FIXME: This produces `addresses/countries` for namespaced models.
|
|
56
|
+
# Should be probably `addresses.countries`
|
|
57
|
+
I18n.t(keys.first, scope: @scope ||= object&.class&.model_name&.collection)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def title_keys
|
|
61
|
+
Array(Jbuilder::Schema.title_name)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def description_keys
|
|
65
|
+
Array(Jbuilder::Schema.description_name)
|
|
48
66
|
end
|
|
49
67
|
end
|
|
50
68
|
|
|
@@ -84,6 +102,7 @@ class Jbuilder::Schema
|
|
|
84
102
|
|
|
85
103
|
def set!(key, value = BLANK, *args, schema: nil, **options, &block)
|
|
86
104
|
old_configuration, @configuration = @configuration, Configuration.build(**schema) if schema&.dig(:object)
|
|
105
|
+
_required << key if schema&.delete(:required) == true
|
|
87
106
|
@within_block = _within_block?(&block)
|
|
88
107
|
|
|
89
108
|
_with_schema_overrides(key => schema) do
|
|
@@ -188,16 +207,18 @@ class Jbuilder::Schema
|
|
|
188
207
|
}
|
|
189
208
|
end
|
|
190
209
|
|
|
191
|
-
def
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
def _set_title_and_description(key, value)
|
|
211
|
+
overrides = @schema_overrides&.dig(key)&.to_h || {}
|
|
212
|
+
return unless overrides.any? || @configuration.object
|
|
213
|
+
|
|
214
|
+
value[:title] ||= overrides[:title] if overrides.key?(:title)
|
|
215
|
+
value[:description] ||= overrides[:description] || @configuration.translate_description(key)
|
|
195
216
|
end
|
|
196
217
|
|
|
197
|
-
def _set_ref(
|
|
198
|
-
ref = {"$ref": "#/#{::Jbuilder::Schema.components_path}/#{
|
|
218
|
+
def _set_ref(object, **options)
|
|
219
|
+
ref = {"$ref": "#/#{::Jbuilder::Schema.components_path}/#{object.split("/").last}"}
|
|
199
220
|
|
|
200
|
-
if array
|
|
221
|
+
if options[:array]
|
|
201
222
|
_attributes.merge! type: :array, items: ref
|
|
202
223
|
else
|
|
203
224
|
_attributes.merge! type: :object, allOf: [ref]
|
|
@@ -209,6 +230,10 @@ class Jbuilder::Schema
|
|
|
209
230
|
@attributes
|
|
210
231
|
end
|
|
211
232
|
|
|
233
|
+
def _required
|
|
234
|
+
@required_keys ||= []
|
|
235
|
+
end
|
|
236
|
+
|
|
212
237
|
FORMATS = {::DateTime => "date-time", ::ActiveSupport::TimeWithZone => "date-time", ::Date => "date", ::Time => "time"}
|
|
213
238
|
|
|
214
239
|
def _schema(key, value, **options)
|
|
@@ -248,7 +273,7 @@ class Jbuilder::Schema
|
|
|
248
273
|
options[:enum] = defined_enum.keys
|
|
249
274
|
end
|
|
250
275
|
|
|
251
|
-
|
|
276
|
+
_set_title_and_description key, options unless within_array
|
|
252
277
|
options
|
|
253
278
|
end
|
|
254
279
|
|
|
@@ -281,7 +306,7 @@ class Jbuilder::Schema
|
|
|
281
306
|
def _set_value(key, value)
|
|
282
307
|
value = _value(value)
|
|
283
308
|
value = _schema(key, value) unless value.is_a?(::Hash) && (value.key?(:type) || value.key?(:allOf)) # rubocop:disable Style/UnlessLogicalOperators
|
|
284
|
-
|
|
309
|
+
_set_title_and_description(key, value)
|
|
285
310
|
super
|
|
286
311
|
end
|
|
287
312
|
|
|
@@ -296,10 +321,20 @@ class Jbuilder::Schema
|
|
|
296
321
|
end
|
|
297
322
|
|
|
298
323
|
def _required!(keys)
|
|
299
|
-
presence_validated_attributes = @configuration.object&.class.try(:validators).to_a.flat_map { _1.attributes if _1.is_a?(::ActiveRecord::Validations::PresenceValidator) }
|
|
324
|
+
presence_validated_attributes = @configuration.object&.class.try(:validators).to_a.flat_map { _1.attributes if _1.is_a?(::ActiveRecord::Validations::PresenceValidator) } + _required
|
|
300
325
|
keys & [_key(:id), *presence_validated_attributes.flat_map { [_key(_1), _key("#{_1}_id")] }]
|
|
301
326
|
end
|
|
302
327
|
|
|
328
|
+
def _within_block?(&block)
|
|
329
|
+
block.present? && _one_line?(block.source)
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def _one_line?(text)
|
|
333
|
+
text = text.gsub("{", " do\n").gsub("}", "\nend").tr(";", "\n")
|
|
334
|
+
lines = text.lines[1..-2].reject { |line| line.strip.empty? || !line.strip.start_with?("json.") }
|
|
335
|
+
lines.size == 1
|
|
336
|
+
end
|
|
337
|
+
|
|
303
338
|
###
|
|
304
339
|
# Jbuilder methods
|
|
305
340
|
###
|
|
@@ -317,15 +352,5 @@ class Jbuilder::Schema
|
|
|
317
352
|
|
|
318
353
|
_merge_values(current_value, value)
|
|
319
354
|
end
|
|
320
|
-
|
|
321
|
-
def _within_block?(&block)
|
|
322
|
-
block.present? && _one_line?(block.source)
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def _one_line?(text)
|
|
326
|
-
text = text.gsub("{", " do\n").gsub("}", "\nend").tr(";", "\n")
|
|
327
|
-
lines = text.lines[1..-2].reject { |line| line.strip.empty? || line.strip.start_with?("#") }
|
|
328
|
-
lines.size == 1
|
|
329
|
-
end
|
|
330
355
|
end
|
|
331
356
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
# We can't use the standard `Jbuilder::Schema::VERSION =` because
|
|
2
2
|
# `Jbuilder` isn't a regular module namespace, but a class …which also loads Active Support.
|
|
3
3
|
# So we use trickery, and assign the proper version once `jbuilder/schema.rb` is loaded.
|
|
4
|
-
JBUILDER_SCHEMA_VERSION = "2.6.
|
|
4
|
+
JBUILDER_SCHEMA_VERSION = "2.6.9"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jbuilder-schema
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.6.
|
|
4
|
+
version: 2.6.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yuri Sidorov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-03-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jbuilder
|
|
@@ -89,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
89
89
|
- !ruby/object:Gem::Version
|
|
90
90
|
version: '0'
|
|
91
91
|
requirements: []
|
|
92
|
-
rubygems_version: 3.
|
|
92
|
+
rubygems_version: 3.5.6
|
|
93
93
|
signing_key:
|
|
94
94
|
specification_version: 4
|
|
95
95
|
summary: Generate JSON Schema from Jbuilder files
|