[Ruby] Add new ruby-idiomatic client generator (opt-in idiomatic redesign)#24220
Open
n-rodriguez wants to merge 1 commit into
Open
[Ruby] Add new ruby-idiomatic client generator (opt-in idiomatic redesign)#24220n-rodriguez wants to merge 1 commit into
ruby-idiomatic client generator (opt-in idiomatic redesign)#24220n-rodriguez wants to merge 1 commit into
Conversation
Member
Contributor
There was a problem hiding this comment.
40 issues found across 792 files
Note: This PR contains a large number of files. cubic only reviews up to 200 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
Re-trigger cubic
n-rodriguez
added a commit
to n-rodriguez/openapi-generator
that referenced
this pull request
Jul 7, 2026
…time bugs From the automated review on PR OpenAPITools#24220: - Faraday only accepts lowercase HTTP method symbols; normalize the method in Connection#call so operations no longer raise ArgumentError on every real call. - Percent-encode path parameters (ERB::Util.url_encode) instead of raw to_s. - Apply authentication PER REQUEST instead of baking it once into the persistent Faraday connection, so access_token / api_key changes (token refresh, credential rotation) take effect on subsequent requests. - Honour the apiKey location: header / query / cookie (not always a header). - Only materialize an OpenAPI `default` for REQUIRED properties; optional fields stay nil so Serializable#to_hash omits them and the server default applies. - Harden the generated GitHub CI workflow with `permissions: contents: read`. Templates only; both samples regenerated, rspec green (16/0, 577/0) and rubocop clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Thanks for the automated review — went through all 40 findings. Pushed fixes for the genuine runtime bugs and want to explain the ones left as-is. Fixed (commit pushed):
Left as designed (with reasoning):
Both samples regenerate green (petstore 16/0, qdrant 577/0) and pass |
Contributor
There was a problem hiding this comment.
2 issues found across 30 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
473e551 to
094af17
Compare
Add `ruby-idiomatic`, a new opt-in Ruby client generator that emits modern, DRY, multi-instance Ruby. It mirrors the Crystal idiomatic redesign as a SEPARATE generator: the existing `ruby` generator, its templates, and its samples are left byte-for-byte unchanged, so users opt in and migrate when they choose. Highlights: - Namespaced sub-clients (`client.dcim.cable_terminations.list`) via a path->route helper (RubyApiRouting) and a hybrid module nesting (moduleName + configurable `apiNamespace` wrapper, resource leaf compact). - A single `Connection#call` choke-point (Faraday) — keyword args everywhere, no `_with_http_info` twins; a delegating `Response` and one rich `ApiError` (all Faraday errors wrapped); per-request auth (header/query/cookie apiKey, basic, bearer) so token refresh/rotation works; a `Configuration#use` Faraday-middleware seam for request signing. - Native multi-instance: a `Client` facade owns a per-instance Configuration/Connection — no global singleton. - Models on a declarative `attribute` DSL + shared `Serializable`/`Validations` mixins; recursive `from_hash` deserializes nested models/arrays/maps/unions/ enums; `additionalProperties` preserved; anyOf/oneOf via a `Polymorphism` helper; array minItems/maxItems validated; numeric enums bare. - Names are always legal Ruby: enum constants and method names derived from digit-leading values/paths get an `N`/`call_` prefix, purely-symbolic enum values (telephony IVR keys `#`/`*`, ...) map to word names, and deeply-nested inline model names are shortened with a deterministic hash suffix to stay under tar's 100-byte path-component limit so `gem build` succeeds. - Class loading via Zeitwerk. A nested `moduleName` (e.g. `Ovh::Api`) is supported: the parent modules are predefined, the loader is driven explicitly, the gemspec reads VERSION by regex, and version.rb is required rather than autoloaded. Acronym names in both model and API resource classes (HTTPConfig, IPRestriction, DedicatedCloud::TwoFAWhitelist, ...) register explicit Zeitwerk inflections from the gem entrypoint so autoloading resolves the real constant instead of raising Zeitwerk::NameError. - Faraday only; form/multipart (incl. file upload); Ruby 3.0 floor; frozen_string_literal on every generated Ruby file; single-quoted strings; path params percent-encoded; FeatureSet declared honestly (JSON only, no XML, allOf/anyOf/oneOf/Union, apiKey/basic/bearer). - Generated gem passes RuboCop clean out of the box: a real `.rubocop.yml` (rubocop-performance/rake/rspec), a modern gemspec with configurable gem* options (author/homepage/summary/license, MIT-aware LICENSE), LICENSE, dev deps + binstubs, `.rspec`, spec_helper (SimpleCov), a commented `.gitignore`, a GitHub Actions CI workflow, and meaningful RSpec. Generated runtime is strict where a caller can err and lenient where the server can drift: model constructors reject unknown keyword args and validate required attributes, Configuration rejects unknown options, and required API params are nil-guarded, while from_hash deserialization bypasses that validation to tolerate server omissions/drift. Authentication is scoped per operation (only the schemes an operation declares are applied, so credentials never leak to `security: []` endpoints); oneOf/anyOf resolve strictly (ambiguous or unmatched payloads raise); JSON parse errors are wrapped in ApiError; deeply-nested request paths keep any base_url path prefix; and a multi-tagged operation yields a single method per path+verb instead of duplicates. Samples: petstore and a real-world Qdrant client, both green and rubocop-clean. Codegen unit tests (RubyIdiomaticClientCodegenTest, RubyApiRoutingTest) pass. A samples CI workflow and the generated generator docs are included. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
094af17 to
2f460af
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a new opt-in Ruby client generator,
ruby-idiomatic, that emits modern, DRY, multi-instance Ruby. It mirrors the recent Crystal idiomatic redesign (#24070) but as a separate generator — the existingrubygenerator, its templates, and its samples are left byte-for-byte unchanged, so there is zero blast radius for its install base. Users opt in with-g ruby-idiomaticand migrate when they choose.What it produces
client.dcim.cable_terminations.listinstead of a flatDcimApiwith prefixed methods (path→route helper + a hybridmodulenesting with a configurableapiNamespacewrapper).Connection#callchoke-point (Faraday) — short declarative operations, keyword args everywhere, no_with_http_infotwins.Response(.data/.status/.headers) and one richApiError(all Faraday errors wrapped).Clientfacade owns a per-instanceConfiguration/Connection; no global singleton.Configuration#useseam to register custom Faraday middleware (request signing à la OVH / AWS SigV4 that a static OpenAPI security scheme cannot model) without subclassing.attributeDSL + sharedSerializable/Validationsmixins (replaces theEnumAttributeValidatorhierarchy and per-model duplication); recursivefrom_hashdeserializes nested models/arrays/maps/unions/enums into typed objects;additionalPropertiespreserved; anyOf/oneOf via aPolymorphismhelper.frozen_string_literaleverywhere; FeatureSet declared honestly (JSON only, no XML, allOf/anyOf/oneOf/Union, apiKey/basic/bearer)..rspec, cleanspec_helper, GitHub Actions CI, and a rich README (incl. the request-signing middleware example). The generated gem passesrubocopclean out of the box (no-Aneeded).Testing / evidence
RubyIdiomaticClientCodegenTest+RubyApiRoutingTest(19 tests) — green.petstore(16 examples, 0 failures) and a real-world Qdrant client undersamples/client/others/ruby-idiomatic-qdrant(577 examples, 0 failures; exercises anyOf / named enums). Both passrubocopwith no offenses.rubygenerator.ruby*samples are untouched.PR checklist
./mvnw clean package, regenerated this generator's samples (./bin/generate-samples.sh bin/configs/ruby-idiomatic*.yaml) and its docs. Only the newruby-idiomaticgenerator's outputs change; no other generator output is affected.cc @wing328 — new opt-in Ruby generator (idiomatic redesign), following up on the Crystal work in #24070.
Summary by cubic
Adds an opt-in Ruby client generator,
ruby-idiomatic, that builds modern, namespaced, multi-instance clients onfaraday+zeitwerk. Ships with generator docs (beta), SPI registration, unit tests, and sample clients (petstore and Qdrant) with CI; adds a samples workflow running petstore RSpec on Ruby 3.0/3.3 and links the new docs entry asruby-idiomatic (beta).New Features
client.collections.points.search).Connection#call(faraday); keyword args only; no_with_http_info.Response(data/status/headers) and richApiErrorwrapping Faraday errors.Configuration/Connection; no globals.Configuration#useto register custom Faraday middleware.attributeDSL with sharedSerializable/Validations; anyOf/oneOf viaPolymorphism; preservesadditionalProperties.faraday,faraday-multipart,zeitwerk.ruby-idiomatic (beta); unit tests; petstore + Qdrant samples with CI; samples workflow monitors both sample paths.Bug Fixes
Connection#call.toApiFilenamefor consistent output and manifests across platforms.Written for commit 2f460af. Summary will update on new commits.