Skip to content

Commit 7bee48f

Browse files
wiebrenclaudewing328
authored
[ruby] fix: enumUnknownDefaultCase declares the unknown-default member but never deserializes to it (#24879)
* fix: [ruby] enumUnknownDefaultCase must reach build_from_hash, not just declare the member With enumUnknownDefaultCase=true the generator adds UNKNOWN_DEFAULT_OPEN_API to every enum class's constants and all_vars, but the enum's build_from_hash still raised 'Invalid ENUM value' for any wire value outside the list — the flag changed nothing observable, and one new enum value from the server still destroyed the whole response. build_from_hash now falls back to the enum's own unknown-default member — the last declared enum var, which under the flag is always the appended UNKNOWN_DEFAULT_OPEN_API. The tolerance lives in each generated enum class; without the flag the generated code is byte-identical to before and still raises. Java's fromValue behavior under the same flag is the reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ * test: [ruby] drop enumUnknownDefaultCase assertions the build_from_hash checks imply Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test: [ruby] keep the enumUnknownDefaultCase member value assertions Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: William Cheng <wing328hk@gmail.com>
1 parent 9f97fc4 commit 7bee48f

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
# @return [String] The enum value
1919
def build_from_hash(value)
2020
return value if {{classname}}.all_vars.include?(value)
21+
{{#enumUnknownDefaultCase}}
22+
{{#allowableValues}}{{#enumVars}}{{#-last}}{{{name}}}{{/-last}}{{/enumVars}}{{/allowableValues}}
23+
{{/enumUnknownDefaultCase}}
24+
{{^enumUnknownDefaultCase}}
2125
raise "Invalid ENUM value #{value} for class #{{{classname}}}"
26+
{{/enumUnknownDefaultCase}}
2227
end
2328
end

‎modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,4 +858,58 @@ public void testAliasModelDoesNotDelegateToItsBuiltInSuperclass() throws Excepti
858858
"def self.acceptable_openapi_nullable\n openapi_nullable\n end");
859859
TestUtils.assertFileNotContains(arrayAlias, "superclass.", "super(attributes)");
860860
}
861+
862+
@Test(description = "enumUnknownDefaultCase=true makes build_from_hash fall back to the unknown default member")
863+
public void testEnumUnknownDefaultCaseBuildFromHashFallback() throws Exception {
864+
final File output = Files.createTempDirectory("test").toFile();
865+
output.deleteOnExit();
866+
867+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/enum.yaml");
868+
CodegenConfig codegenConfig = new RubyClientCodegen();
869+
codegenConfig.additionalProperties().put(CodegenConstants.ENUM_UNKNOWN_DEFAULT_CASE, "true");
870+
codegenConfig.setOutputDir(output.getAbsolutePath());
871+
872+
ClientOptInput clientOptInput = new ClientOptInput().openAPI(openAPI).config(codegenConfig);
873+
new DefaultGenerator().opts(clientOptInput).generate();
874+
875+
Path stringEnum = new File(output, "lib/openapi_client/models/type.rb").toPath();
876+
TestUtils.assertFileContains(stringEnum, "UNKNOWN_DEFAULT_OPEN_API = \"unknown_default_open_api\".freeze");
877+
TestUtils.assertFileContains(stringEnum,
878+
"def build_from_hash(value)\n" +
879+
" return value if Type.all_vars.include?(value)\n" +
880+
" UNKNOWN_DEFAULT_OPEN_API\n" +
881+
" end");
882+
TestUtils.assertFileNotContains(stringEnum, "raise \"Invalid ENUM value");
883+
884+
// the integer enum's unknown-default member keeps its (pre-existing) numeric-prefixed name
885+
Path integerEnum = new File(output, "lib/openapi_client/models/integer_enum.rb").toPath();
886+
TestUtils.assertFileContains(integerEnum, "Nunknown_default_open_api = 11184809.freeze");
887+
TestUtils.assertFileContains(integerEnum,
888+
"def build_from_hash(value)\n" +
889+
" return value if IntegerEnum.all_vars.include?(value)\n" +
890+
" Nunknown_default_open_api\n" +
891+
" end");
892+
TestUtils.assertFileNotContains(integerEnum, "raise \"Invalid ENUM value");
893+
}
894+
895+
@Test(description = "without enumUnknownDefaultCase build_from_hash still raises on unknown values")
896+
public void testEnumBuildFromHashRaisesByDefault() throws Exception {
897+
final File output = Files.createTempDirectory("test").toFile();
898+
output.deleteOnExit();
899+
900+
final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/enum.yaml");
901+
CodegenConfig codegenConfig = new RubyClientCodegen();
902+
codegenConfig.setOutputDir(output.getAbsolutePath());
903+
904+
ClientOptInput clientOptInput = new ClientOptInput().openAPI(openAPI).config(codegenConfig);
905+
new DefaultGenerator().opts(clientOptInput).generate();
906+
907+
Path stringEnum = new File(output, "lib/openapi_client/models/type.rb").toPath();
908+
TestUtils.assertFileNotContains(stringEnum, "UNKNOWN_DEFAULT_OPEN_API");
909+
TestUtils.assertFileContains(stringEnum,
910+
"def build_from_hash(value)\n" +
911+
" return value if Type.all_vars.include?(value)\n" +
912+
" raise \"Invalid ENUM value #{value} for class #Type\"\n" +
913+
" end");
914+
}
861915
}

0 commit comments

Comments
 (0)