haveapi 0.29.1 → 0.29.2
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 +21 -0
- data/haveapi.gemspec +1 -1
- data/lib/haveapi/parameters/metadata_i18n.rb +80 -3
- data/lib/haveapi/parameters/typed.rb +5 -1
- data/lib/haveapi/version.rb +1 -1
- data/spec/i18n_spec.rb +36 -0
- data/spec/params_spec.rb +18 -0
- 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: 3de67ba481b9c0e88a56b07403e1979e24558ee8f52f3c1eb9d720faa442a62b
|
|
4
|
+
data.tar.gz: 1d3d0d435612eceeba75ec9973082f7eeca6fd8f7c5010197cb324edd606c843
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40fcf28b778528046eab97d60034de89210b41c3e7977f12d622c0b8248bc89c231663eb355b5284693db781a3f25887c719ec6ca76effbfb604a10a914762e2
|
|
7
|
+
data.tar.gz: 7cd757b4ff23dfdd3dbe5efd732ceb23c6adb1bc763ed117de84687ee5c23652a7e71332e7f8762b94eca198b5b5cdbd76a2cf2f5698b876b9032343b98e1fab
|
data/README.md
CHANGED
|
@@ -328,6 +328,27 @@ cs:
|
|
|
328
328
|
label: "Hostname"
|
|
329
329
|
```
|
|
330
330
|
|
|
331
|
+
Choice labels declared through the `choices`/`include` validator use the same
|
|
332
|
+
parameter metadata path with `choices.<value>.label` appended. If choices were
|
|
333
|
+
declared as a value-to-label map, the declared label is used as the English
|
|
334
|
+
fallback. If choices were declared as an array, untranslated self-description
|
|
335
|
+
keeps the array form; a locale that supplies labels is returned as the existing
|
|
336
|
+
HaveAPI `{value: label}` map form.
|
|
337
|
+
|
|
338
|
+
```yaml
|
|
339
|
+
cs:
|
|
340
|
+
my_api:
|
|
341
|
+
resources:
|
|
342
|
+
vps:
|
|
343
|
+
attributes:
|
|
344
|
+
state:
|
|
345
|
+
choices:
|
|
346
|
+
running:
|
|
347
|
+
label: "bezi"
|
|
348
|
+
stopped:
|
|
349
|
+
label: "vypnuto"
|
|
350
|
+
```
|
|
351
|
+
|
|
331
352
|
Metadata parameters fall back through resource and global metadata keys:
|
|
332
353
|
|
|
333
354
|
```yaml
|
data/haveapi.gemspec
CHANGED
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
s.required_ruby_version = ">= #{File.read('../../.ruby-version').strip}"
|
|
16
16
|
|
|
17
17
|
s.add_dependency 'activesupport', '>= 7.1'
|
|
18
|
-
s.add_dependency 'haveapi-client', '~> 0.29.
|
|
18
|
+
s.add_dependency 'haveapi-client', '~> 0.29.2'
|
|
19
19
|
s.add_dependency 'i18n', '>= 1.6', '< 2'
|
|
20
20
|
s.add_dependency 'json'
|
|
21
21
|
s.add_dependency 'mail'
|
|
@@ -14,7 +14,7 @@ module HaveAPI::Parameters
|
|
|
14
14
|
keys:,
|
|
15
15
|
value:
|
|
16
16
|
}
|
|
17
|
-
end
|
|
17
|
+
end + choice_i18n_catalog_items(context, i18n_path)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
private
|
|
@@ -27,6 +27,17 @@ module HaveAPI::Parameters
|
|
|
27
27
|
localized_metadata(context, i18n_path, :description, @desc)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def localized_validators(context, i18n_path, validators)
|
|
31
|
+
include_validator = validators[:include]
|
|
32
|
+
return validators unless include_validator && include_validator.has_key?(:values)
|
|
33
|
+
|
|
34
|
+
values = include_validator.fetch(:values)
|
|
35
|
+
localized_values = localized_choice_values(context, i18n_path, values)
|
|
36
|
+
return validators if localized_values.equal?(values)
|
|
37
|
+
|
|
38
|
+
validators.merge(include: include_validator.merge(values: localized_values))
|
|
39
|
+
end
|
|
40
|
+
|
|
30
41
|
def localized_metadata(context, i18n_path, kind, fallback)
|
|
31
42
|
keys = metadata_i18n_keys(context, i18n_path, kind, fallback)
|
|
32
43
|
default = HaveAPI.localize(fallback)
|
|
@@ -61,6 +72,74 @@ module HaveAPI::Parameters
|
|
|
61
72
|
[exact_key, *metadata_i18n_default_keys(context, i18n_path, kind, scope)].uniq
|
|
62
73
|
end
|
|
63
74
|
|
|
75
|
+
def localized_choice_values(context, i18n_path, values)
|
|
76
|
+
case values
|
|
77
|
+
when ::Hash
|
|
78
|
+
values.to_h do |value, label|
|
|
79
|
+
[
|
|
80
|
+
value,
|
|
81
|
+
localized_metadata(context, i18n_path, choice_i18n_kind(value), label)
|
|
82
|
+
]
|
|
83
|
+
end
|
|
84
|
+
when ::Array
|
|
85
|
+
localized = values.to_h do |value|
|
|
86
|
+
label = localized_metadata(
|
|
87
|
+
context,
|
|
88
|
+
i18n_path,
|
|
89
|
+
choice_i18n_kind(value),
|
|
90
|
+
value.to_s
|
|
91
|
+
)
|
|
92
|
+
[value, label]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
localized.any? { |value, label| label.to_s != value.to_s } ? localized : values
|
|
96
|
+
else
|
|
97
|
+
values
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def choice_i18n_catalog_items(context, i18n_path)
|
|
102
|
+
values = choice_i18n_values
|
|
103
|
+
return [] unless values
|
|
104
|
+
|
|
105
|
+
choice_i18n_fallbacks(values).filter_map do |value, fallback|
|
|
106
|
+
keys = metadata_i18n_keys(context, i18n_path, choice_i18n_kind(value), fallback)
|
|
107
|
+
label = HaveAPI.localize(fallback).to_s.strip
|
|
108
|
+
|
|
109
|
+
next if keys.empty? || label.empty?
|
|
110
|
+
|
|
111
|
+
{
|
|
112
|
+
param: HaveAPI::Params.i18n_segment(@name),
|
|
113
|
+
kind: metadata_i18n_key_suffix(choice_i18n_kind(value)),
|
|
114
|
+
keys:,
|
|
115
|
+
value: label
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def choice_i18n_values
|
|
121
|
+
metadata_i18n_choice_values
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def metadata_i18n_choice_values
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def choice_i18n_fallbacks(values)
|
|
129
|
+
case values
|
|
130
|
+
when ::Hash
|
|
131
|
+
values
|
|
132
|
+
when ::Array
|
|
133
|
+
values.to_h { |value| [value, value.to_s] }
|
|
134
|
+
else
|
|
135
|
+
{}
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def choice_i18n_kind(value)
|
|
140
|
+
"choices.#{HaveAPI::Params.i18n_segment(value)}.label"
|
|
141
|
+
end
|
|
142
|
+
|
|
64
143
|
def metadata_i18n_fallback(kind)
|
|
65
144
|
case kind
|
|
66
145
|
when :label
|
|
@@ -78,8 +157,6 @@ module HaveAPI::Parameters
|
|
|
78
157
|
@label_key
|
|
79
158
|
when :description
|
|
80
159
|
@desc_key
|
|
81
|
-
else
|
|
82
|
-
raise ArgumentError, "unsupported parameter metadata kind #{kind.inspect}"
|
|
83
160
|
end
|
|
84
161
|
end
|
|
85
162
|
|
|
@@ -62,7 +62,7 @@ module HaveAPI::Parameters
|
|
|
62
62
|
label: localized_label(context, i18n_path),
|
|
63
63
|
description: localized_description(context, i18n_path),
|
|
64
64
|
type: @type ? @type.to_s : String.to_s,
|
|
65
|
-
validators: @validators ? @validators.describe : {},
|
|
65
|
+
validators: @validators ? localized_validators(context, i18n_path, @validators.describe) : {},
|
|
66
66
|
default: @default,
|
|
67
67
|
protected: @protected || false
|
|
68
68
|
}
|
|
@@ -167,6 +167,10 @@ module HaveAPI::Parameters
|
|
|
167
167
|
@type == Custom
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
+
def metadata_i18n_choice_values
|
|
171
|
+
@validators&.describe&.dig(:include, :values)
|
|
172
|
+
end
|
|
173
|
+
|
|
170
174
|
def normalize_custom_keys(value)
|
|
171
175
|
case value
|
|
172
176
|
when ::Hash
|
data/lib/haveapi/version.rb
CHANGED
data/spec/i18n_spec.rb
CHANGED
|
@@ -48,6 +48,14 @@ describe HaveAPI::I18n do
|
|
|
48
48
|
string :global_attr_label,
|
|
49
49
|
label: 'Global attribute fallback',
|
|
50
50
|
desc: 'Global attribute description fallback'
|
|
51
|
+
string :status, choices: %i[enabled disabled]
|
|
52
|
+
string :priority,
|
|
53
|
+
choices: {
|
|
54
|
+
values: {
|
|
55
|
+
low: 'Low priority',
|
|
56
|
+
high: 'High priority'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
51
59
|
string :code, length: {
|
|
52
60
|
min: 3,
|
|
53
61
|
message: HaveAPI.message('haveapi.validators.length.min', min: 3)
|
|
@@ -146,6 +154,14 @@ describe HaveAPI::I18n do
|
|
|
146
154
|
expect(length[:message]).to eq('délka musí být v rozsahu <3, 5>')
|
|
147
155
|
end
|
|
148
156
|
|
|
157
|
+
it 'keeps untranslated array choices unchanged in OPTIONS responses' do
|
|
158
|
+
header 'Accept', 'application/json'
|
|
159
|
+
options '/v1/things', method: 'POST'
|
|
160
|
+
|
|
161
|
+
choices = api_response[:input][:parameters][:status][:validators][:include]
|
|
162
|
+
expect(choices[:values]).to eq(%w[enabled disabled])
|
|
163
|
+
end
|
|
164
|
+
|
|
149
165
|
it 'localizes API metadata in OPTIONS responses' do
|
|
150
166
|
previous_available = ::I18n.available_locales
|
|
151
167
|
::I18n.available_locales = (previous_available + %i[en cs]).uniq
|
|
@@ -218,6 +234,18 @@ describe HaveAPI::I18n do
|
|
|
218
234
|
global_attr_label: {
|
|
219
235
|
label: 'Přesný globální popisek',
|
|
220
236
|
description: 'Přesný globální popis'
|
|
237
|
+
},
|
|
238
|
+
status: {
|
|
239
|
+
choices: {
|
|
240
|
+
enabled: { label: 'Zapnuto' },
|
|
241
|
+
disabled: { label: 'Vypnuto' }
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
priority: {
|
|
245
|
+
choices: {
|
|
246
|
+
low: { label: 'Nízká priorita' },
|
|
247
|
+
high: { label: 'Vysoká priorita' }
|
|
248
|
+
}
|
|
221
249
|
}
|
|
222
250
|
},
|
|
223
251
|
output: {
|
|
@@ -325,6 +353,14 @@ describe HaveAPI::I18n do
|
|
|
325
353
|
label: 'Přesný globální popisek',
|
|
326
354
|
description: 'Přesný globální popis'
|
|
327
355
|
)
|
|
356
|
+
expect(input_params[:status][:validators][:include][:values]).to eq(
|
|
357
|
+
enabled: 'Zapnuto',
|
|
358
|
+
disabled: 'Vypnuto'
|
|
359
|
+
)
|
|
360
|
+
expect(input_params[:priority][:validators][:include][:values]).to eq(
|
|
361
|
+
low: 'Nízká priorita',
|
|
362
|
+
high: 'Vysoká priorita'
|
|
363
|
+
)
|
|
328
364
|
expect(input_params[:count]).to include(
|
|
329
365
|
label: 'Count',
|
|
330
366
|
description: nil
|
data/spec/params_spec.rb
CHANGED
|
@@ -258,6 +258,8 @@ describe HaveAPI::Params do
|
|
|
258
258
|
p = described_class.new(:input, ParamsSpec::MyResource::Index)
|
|
259
259
|
p.add_block(proc do
|
|
260
260
|
string :hostname, label: 'Hostname', desc: 'VPS hostname'
|
|
261
|
+
string :state, choices: %i[queued running]
|
|
262
|
+
string :priority, choices: { values: { low: 'Low priority' } }
|
|
261
263
|
string :framework,
|
|
262
264
|
label: HaveAPI.message('haveapi.parameters.metadata.no.label')
|
|
263
265
|
end)
|
|
@@ -274,6 +276,22 @@ describe HaveAPI::Params do
|
|
|
274
276
|
params_spec.attributes.hostname.label
|
|
275
277
|
])
|
|
276
278
|
expect(items.none? { |item| item[:param] == 'framework' }).to be true
|
|
279
|
+
|
|
280
|
+
choice = items.detect do |item|
|
|
281
|
+
item[:param] == 'state' && item[:kind] == 'choices.queued.label'
|
|
282
|
+
end
|
|
283
|
+
expect(choice[:value]).to eq('queued')
|
|
284
|
+
expect(choice[:keys]).to eq(%w[
|
|
285
|
+
params_spec.resources.my_resource.actions.index.input.state.choices.queued.label
|
|
286
|
+
params_spec.resources.my_resource.input.state.choices.queued.label
|
|
287
|
+
params_spec.resources.my_resource.attributes.state.choices.queued.label
|
|
288
|
+
params_spec.attributes.state.choices.queued.label
|
|
289
|
+
])
|
|
290
|
+
|
|
291
|
+
choice = items.detect do |item|
|
|
292
|
+
item[:param] == 'priority' && item[:kind] == 'choices.low.label'
|
|
293
|
+
end
|
|
294
|
+
expect(choice[:value]).to eq('Low priority')
|
|
277
295
|
end
|
|
278
296
|
|
|
279
297
|
it 'does not parse meta resource path segments as metadata paths' do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: haveapi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.29.
|
|
4
|
+
version: 0.29.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jakub Skokan
|
|
@@ -29,14 +29,14 @@ dependencies:
|
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.29.
|
|
32
|
+
version: 0.29.2
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.29.
|
|
39
|
+
version: 0.29.2
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: i18n
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|