Skip to content

Commit 522faf8

Browse files
[ruby] fix oneOf handling (#5706)
* [ruby] fix oneOf handling * use previous ruby configs due to issue #4690 * check for oneOf model in base_object * validate the attributes in partial_oneof_module
1 parent 6f6822a commit 522faf8

File tree

221 files changed

+2719
-1732
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

221 files changed

+2719
-1732
lines changed

modules/openapi-generator/src/main/resources/ruby-client/api_client.mustache

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,9 @@ module {{moduleName}}
149149
data.each { |k, v| hash[k] = convert_to_type(v, sub_type) }
150150
end
151151
else
152-
# models, e.g. Pet
153-
{{moduleName}}.const_get(return_type).build_from_hash(data)
152+
# models (e.g. Pet) or oneOf
153+
klass = {{moduleName}}.const_get(return_type)
154+
klass.respond_to?(:openapi_one_of) ? klass.build(data) : klass.build_from_hash(data)
154155
end
155156
end
156157

modules/openapi-generator/src/main/resources/ruby-client/api_doc.mustache

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
All URIs are relative to *{{basePath}}*
66

7-
Method | HTTP request | Description
8-
------------- | ------------- | -------------
9-
{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
10-
{{/operation}}{{/operations}}
7+
| Method | HTTP request | Description |
8+
| ------ | ------------ | ----------- |
9+
{{#operations}}
10+
{{#operation}}
11+
| [**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} |
12+
{{/operation}}
13+
{{/operations}}
1114

1215
{{#operations}}
1316
{{#operation}}
@@ -67,10 +70,15 @@ end
6770

6871
### Parameters
6972

70-
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
71-
Name | Type | Description | Notes
72-
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}
73-
{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}}| {{description}} | {{^required}}[optional] {{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}}
73+
{{^allParams}}
74+
This endpoint does not need any parameter.
75+
{{/allParams}}
76+
{{#allParams}}
77+
{{#-first}}
78+
| Name | Type | Description | Notes |
79+
| ---- | ---- | ----------- | ----- |
80+
{{/-first}}
81+
| **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}[**{{dataType}}**]({{baseType}}.md){{/isFile}}{{/isPrimitiveType}} | {{description}} | {{^required}}[optional]{{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} |
7482
{{/allParams}}
7583

7684
### Return type

modules/openapi-generator/src/main/resources/ruby-client/base_object.mustache

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@
6767
end
6868
end
6969
else # model
70-
{{moduleName}}.const_get(type).build_from_hash(value)
70+
# models (e.g. Pet) or oneOf
71+
klass = {{moduleName}}.const_get(type)
72+
klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
7173
end
7274
end
7375

@@ -93,7 +95,7 @@
9395
is_nullable = self.class.openapi_nullable.include?(attr)
9496
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
9597
end
96-
98+
9799
hash[param] = _to_hash(value)
98100
end
99101
hash

modules/openapi-generator/src/main/resources/ruby-client/model.mustache

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,14 @@ module {{moduleName}}
1212
{{>partial_model_enum_class}}
1313
{{/isEnum}}
1414
{{^isEnum}}
15+
{{#oneOf}}
16+
{{#-first}}
17+
{{>partial_oneof_module}}
18+
{{/-first}}
19+
{{/oneOf}}
20+
{{^oneOf}}
1521
{{>partial_model_generic}}
22+
{{/oneOf}}
1623
{{/isEnum}}
1724
{{/model}}
1825
{{/models}}
Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
1-
{{#models}}{{#model}}# {{moduleName}}::{{classname}}
2-
3-
## Properties
4-
5-
Name | Type | Description | Notes
6-
------------ | ------------- | ------------- | -------------
7-
{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}}
8-
{{/vars}}
9-
10-
## Code Sample
11-
12-
```ruby
13-
require '{{moduleName}}'
14-
15-
instance = {{moduleName}}::{{classname}}.new({{#vars}}{{name}}: {{example}}{{^-last}},
16-
{{/-last}}{{/vars}})
17-
```
18-
19-
{{/model}}{{/models}}
1+
{{#models}}
2+
{{#model}}
3+
{{#oneOf}}
4+
{{#-first}}
5+
{{>partial_oneof_module_doc}}
6+
{{/-first}}
7+
{{/oneOf}}
8+
{{^oneOf}}
9+
{{>partial_model_generic_doc}}
10+
{{/oneOf}}
11+
{{/model}}
12+
{{/models}}

modules/openapi-generator/src/main/resources/ruby-client/model_test.mustache

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,13 @@ require 'date'
1111
# Please update as you see appropriate
1212
{{#models}}
1313
{{#model}}
14-
describe '{{classname}}' do
15-
before do
16-
# run before each test
17-
@instance = {{moduleName}}::{{classname}}.new
18-
end
19-
20-
after do
21-
# run after each test
22-
end
14+
describe {{moduleName}}::{{classname}} do
15+
{{^oneOf}}
16+
let(:instance) { {{moduleName}}::{{classname}}.new }
2317

2418
describe 'test an instance of {{classname}}' do
2519
it 'should create an instance of {{classname}}' do
26-
expect(@instance).to be_instance_of({{moduleName}}::{{classname}})
20+
expect(instance).to be_instance_of({{moduleName}}::{{classname}})
2721
end
2822
end
2923
{{#vars}}
@@ -33,7 +27,7 @@ describe '{{classname}}' do
3327
# assertion here. ref: https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
3428
# validator = Petstore::EnumTest::EnumAttributeValidator.new('{{{dataType}}}', [{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}])
3529
# validator.allowable_values.each do |value|
36-
# expect { @instance.{{name}} = value }.not_to raise_error
30+
# expect { instance.{{name}} = value }.not_to raise_error
3731
# end
3832
{{/isEnum}}
3933
{{^isEnum}}
@@ -43,6 +37,42 @@ describe '{{classname}}' do
4337
end
4438

4539
{{/vars}}
40+
{{/oneOf}}
41+
{{#oneOf}}
42+
{{#-first}}
43+
describe '.openapi_one_of' do
44+
it 'lists the models referenced in the oneOf array' do
45+
expect(described_class.openapi_one_of).to_not be_empty
46+
described_class.openapi_one_of.each { |klass| expect { {{moduleName}}.const_get(klass) }.to_not raise_error }
47+
end
48+
end
49+
50+
{{#discriminator}}
51+
{{#propertyName}}
52+
describe '.openapi_discriminator_name' do
53+
it 'returns the value of the "discriminator" property' do
54+
expect(described_class.openapi_discriminator_name).to_not be_empty
55+
end
56+
end
57+
58+
{{/propertyName}}
59+
{{#mappedModels}}
60+
{{#-first}}
61+
describe '.openapi_discriminator_mapping' do
62+
it 'returns the key/values of the "mapping" property' do
63+
expect(described_class.openapi_discriminator_mapping.values.sort).to eq(described_class.openapi_one_of.sort)
64+
end
65+
end
66+
67+
{{/-first}}
68+
{{/mappedModels}}
69+
{{/discriminator}}
70+
describe '.build' do
71+
it 'returns the correct model' do
72+
end
73+
end
74+
{{/-first}}
75+
{{/oneOf}}
4676
end
4777
{{/model}}
4878
{{/models}}

modules/openapi-generator/src/main/resources/ruby-client/partial_model_generic.mustache

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
}
4343
end
4444

45+
# Returns all the JSON keys this model knows about{{#parent}}, including the ones defined in its parent(s){{/parent}}
46+
def self.acceptable_attributes
47+
{{^parent}}
48+
attribute_map.values
49+
{{/parent}}
50+
{{#parent}}
51+
attribute_map.values.concat(superclass.acceptable_attributes)
52+
{{/parent}}
53+
end
54+
4555
# Attribute type mapping.
4656
def self.openapi_types
4757
{
@@ -75,19 +85,6 @@
7585

7686
{{/-last}}
7787
{{/anyOf}}
78-
{{#oneOf}}
79-
{{#-first}}
80-
# List of class defined in oneOf (OpenAPI v3)
81-
def self.openapi_one_of
82-
[
83-
{{/-first}}
84-
:'{{{.}}}'{{^-last}},{{/-last}}
85-
{{#-last}}
86-
]
87-
end
88-
89-
{{/-last}}
90-
{{/oneOf}}
9188
{{#allOf}}
9289
{{#-first}}
9390
# List of class defined in allOf (OpenAPI v3)
@@ -270,26 +267,6 @@
270267

271268
{{/-first}}
272269
{{/anyOf}}
273-
{{#oneOf}}
274-
{{#-first}}
275-
_one_of_found = false
276-
self.class.openapi_one_of.each do |_class|
277-
_one_of = {{moduleName}}.const_get(_class).build_from_hash(self.to_hash)
278-
if _one_of.valid?
279-
if _one_of_found
280-
return false
281-
else
282-
_one_of_found = true
283-
end
284-
end
285-
end
286-
287-
if !_one_of_found
288-
return false
289-
end
290-
291-
{{/-first}}
292-
{{/oneOf}}
293270
true{{#parent}} && super{{/parent}}
294271
end
295272

@@ -391,4 +368,4 @@
391368
end
392369

393370
{{> base_object}}
394-
end
371+
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# {{moduleName}}::{{classname}}
2+
3+
## Properties
4+
5+
| Name | Type | Description | Notes |
6+
| ---- | ---- | ----------- | ----- |
7+
{{#vars}}
8+
| **{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional]{{/required}}{{#isReadOnly}}[readonly]{{/isReadOnly}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} |
9+
{{/vars}}
10+
11+
## Code Sample
12+
13+
```ruby
14+
require '{{{gemName}}}'
15+
16+
{{^vars}}
17+
instance = {{moduleName}}::{{classname}}.new()
18+
{{/vars}}
19+
{{#vars}}
20+
{{#-first}}
21+
instance = {{moduleName}}::{{classname}}.new(
22+
{{/-first}}
23+
{{name}}: {{example}}{{^-last}},{{/-last}}
24+
{{#-last}}
25+
)
26+
{{/-last}}
27+
{{/vars}}
28+
```

0 commit comments

Comments
 (0)