From 0ac93a4941839b5f125a84ef636a59cfae4b8e81 Mon Sep 17 00:00:00 2001 From: maikdijkstra Date: Wed, 10 Sep 2025 16:43:21 +0200 Subject: [PATCH] fix(ruby-client): Fix incorrect boolean parsing in OneOf/AnyOf Changes the logic of parsing of OneOf/AnyOf to fix incorrect type coercion in OneOf/AnyOf contexts. The guard which checks whether typed_data is true-ish fails for booleans. If the oneOf includes a boolean type and the data is false then it will correctly parse this value as a boolean. However, the guard class will determine that false is not true-ish and therefore returns nil. So the result of the type coercion of false will be nil. This can result in problems when dealing with default true. For example how a false can turn into a true with defaults: 1. The API returns false 2. The type coercion determines false becomes nil 3. When storing this retrieved record with a default of true for this column the stored value is suddenly true while the API specifically returned false This fix removes this guard and will rely on the exception raised to return nil when type coercion fails. --- .../ruby-client/partial_anyof_module.mustache | 3 +- .../ruby-client/partial_oneof_module.mustache | 3 +- ...ith-fake-endpoints-models-for-testing.yaml | 30 +++++ .../ruby-httpx/.openapi-generator/FILES | 2 + samples/client/petstore/ruby-httpx/README.md | 1 + .../ruby-httpx/docs/OneOfPrimitiveTypes.md | 69 +++++++++++ .../petstore/ruby-httpx/lib/petstore.rb | 1 + .../lib/petstore/models/mammal_anyof.rb | 3 +- .../models/mammal_without_discriminator.rb | 3 +- .../petstore/models/one_of_primitive_types.rb | 114 ++++++++++++++++++ .../models/one_of_primitive_types_spec.rb | 32 +++++ .../petstore/ruby/.openapi-generator/FILES | 2 + samples/client/petstore/ruby/README.md | 1 + .../petstore/ruby/docs/OneOfPrimitiveTypes.md | 69 +++++++++++ samples/client/petstore/ruby/lib/petstore.rb | 1 + .../ruby/lib/petstore/models/mammal_anyof.rb | 3 +- .../models/mammal_without_discriminator.rb | 3 +- .../petstore/models/one_of_primitive_types.rb | 114 ++++++++++++++++++ .../petstore/ruby/spec/custom/model_spec.rb | 105 +++++++++++++++- .../models/one_of_primitive_types_spec.rb | 32 +++++ 20 files changed, 576 insertions(+), 15 deletions(-) create mode 100644 samples/client/petstore/ruby-httpx/docs/OneOfPrimitiveTypes.md create mode 100644 samples/client/petstore/ruby-httpx/lib/petstore/models/one_of_primitive_types.rb create mode 100644 samples/client/petstore/ruby-httpx/spec/models/one_of_primitive_types_spec.rb create mode 100644 samples/client/petstore/ruby/docs/OneOfPrimitiveTypes.md create mode 100644 samples/client/petstore/ruby/lib/petstore/models/one_of_primitive_types.rb create mode 100644 samples/client/petstore/ruby/spec/models/one_of_primitive_types_spec.rb diff --git a/modules/openapi-generator/src/main/resources/ruby-client/partial_anyof_module.mustache b/modules/openapi-generator/src/main/resources/ruby-client/partial_anyof_module.mustache index f979fdd3100e..040a52199e00 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/partial_anyof_module.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/partial_anyof_module.mustache @@ -29,8 +29,7 @@ openapi_any_of.each do |klass| begin next if klass == :AnyType # "nullable: true" - typed_data = find_and_cast_into_type(klass, data) - return typed_data if typed_data + return find_and_cast_into_type(klass, data) rescue # rescue all errors so we keep iterating even if the current item lookup raises end end diff --git a/modules/openapi-generator/src/main/resources/ruby-client/partial_oneof_module.mustache b/modules/openapi-generator/src/main/resources/ruby-client/partial_oneof_module.mustache index 8dd7b381d2bd..04fa0d311024 100644 --- a/modules/openapi-generator/src/main/resources/ruby-client/partial_oneof_module.mustache +++ b/modules/openapi-generator/src/main/resources/ruby-client/partial_oneof_module.mustache @@ -69,8 +69,7 @@ openapi_one_of.each do |klass| begin next if klass == :AnyType # "nullable: true" - typed_data = find_and_cast_into_type(klass, data) - return typed_data if typed_data + return find_and_cast_into_type(klass, data) rescue # rescue all errors so we keep iterating even if the current item lookup raises end end diff --git a/modules/openapi-generator/src/test/resources/3_0/ruby/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/ruby/petstore-with-fake-endpoints-models-for-testing.yaml index 9cdb45fcd65d..064862059da5 100644 --- a/modules/openapi-generator/src/test/resources/3_0/ruby/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/ruby/petstore-with-fake-endpoints-models-for-testing.yaml @@ -2162,3 +2162,33 @@ components: type: string type_: type: string + OneOfPrimitiveTypes: + oneOf: + - type: string + - type: number + - type: integer + - type: boolean + - type: string + format: date + - type: string + format: date-time + - type: array + items: + type: string + - type: array + items: + type: number + - type: array + items: + type: integer + - type: array + items: + type: boolean + - type: array + items: + type: string + format: date + - type: array + items: + type: string + format: date-time diff --git a/samples/client/petstore/ruby-httpx/.openapi-generator/FILES b/samples/client/petstore/ruby-httpx/.openapi-generator/FILES index 7bc5bf3b003e..fa488c13b2d9 100644 --- a/samples/client/petstore/ruby-httpx/.openapi-generator/FILES +++ b/samples/client/petstore/ruby-httpx/.openapi-generator/FILES @@ -48,6 +48,7 @@ docs/Name.md docs/NullableClass.md docs/NumberOnly.md docs/ObjectWithDeprecatedFields.md +docs/OneOfPrimitiveTypes.md docs/Order.md docs/OuterComposite.md docs/OuterEnum.md @@ -118,6 +119,7 @@ lib/petstore/models/name.rb lib/petstore/models/nullable_class.rb lib/petstore/models/number_only.rb lib/petstore/models/object_with_deprecated_fields.rb +lib/petstore/models/one_of_primitive_types.rb lib/petstore/models/order.rb lib/petstore/models/outer_composite.rb lib/petstore/models/outer_enum.rb diff --git a/samples/client/petstore/ruby-httpx/README.md b/samples/client/petstore/ruby-httpx/README.md index 3805aba77108..587ccdfcb967 100644 --- a/samples/client/petstore/ruby-httpx/README.md +++ b/samples/client/petstore/ruby-httpx/README.md @@ -164,6 +164,7 @@ Class | Method | HTTP request | Description - [Petstore::NullableClass](docs/NullableClass.md) - [Petstore::NumberOnly](docs/NumberOnly.md) - [Petstore::ObjectWithDeprecatedFields](docs/ObjectWithDeprecatedFields.md) + - [Petstore::OneOfPrimitiveTypes](docs/OneOfPrimitiveTypes.md) - [Petstore::Order](docs/Order.md) - [Petstore::OuterComposite](docs/OuterComposite.md) - [Petstore::OuterEnum](docs/OuterEnum.md) diff --git a/samples/client/petstore/ruby-httpx/docs/OneOfPrimitiveTypes.md b/samples/client/petstore/ruby-httpx/docs/OneOfPrimitiveTypes.md new file mode 100644 index 000000000000..9023811f8f1c --- /dev/null +++ b/samples/client/petstore/ruby-httpx/docs/OneOfPrimitiveTypes.md @@ -0,0 +1,69 @@ +# Petstore::OneOfPrimitiveTypes + +## Class instance methods + +### `openapi_one_of` + +Returns the list of classes defined in oneOf. + +#### Example + +```ruby +require 'petstore' + +Petstore::OneOfPrimitiveTypes.openapi_one_of +# => +# [ +# :'Array', +# :'Array', +# :'Array', +# :'Array', +# :'Array', +# :'Array