Skip to content

[BUG][RUBY-NEXTGEN] Nested resources are not reachable from the client #24999

Description

@wiebren

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

ruby-nextgen puts nested resources in their own class (/stables/{stable}/ponies/{pony} → Api::Stables::Ponies), but the client offers no way to reach them. RubyNextgenClientCodegen#postProcessSupportingFileData computes a resources list for each namespace in rbNamespaces, but client.mustache only renders the namespace accessors, and the namespace class has no accessors either. The only way to call a nested operation is Petstore::Api::Stables::Ponies.new(client.connection).

If a namespace has only nested paths (no /stables or /stables/{stable} operation), it gets worse: Zeitwerk makes Api::Stables an implicit module from the api/stables/ directory, and the generated client.stables accessor calls Stables.new on it, which raises NoMethodError: undefined method 'new' for module Petstore::Api::Stables.

openapi-generator version

master, 7.26.0-SNAPSHOT, 05b61f34d7fb0199330e1d6c57e6159f72427837

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: nested
  version: 1.0.0
paths:
  /stables:
    get:
      operationId: listStables
      responses:
        '200':
          description: OK
  /stables/{stable}:
    get:
      operationId: getStable
      parameters:
        - name: stable
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
  /stables/{stable}/ponies/{pony}:
    get:
      operationId: getPony
      parameters:
        - name: stable
          in: path
          required: true
          schema:
            type: string
        - name: pony
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
Generation Details
java -jar openapi-generator-cli.jar generate -g ruby-nextgen -i spec.yaml -o out \
  --additional-properties=gemName=petstore,moduleName=Petstore

This generates api/stables.rb (Stables#get, Stables#list) and api/stables/ponies.rb (Stables::Ponies#get). Generated lib/petstore/client.rb:

module Petstore
  class Client
    attr_reader :configuration, :connection

    def initialize(base_url: nil, **options, &block)
      @configuration = Configuration.new(base_url: base_url, **options, &block)
      @connection = Connection.new(@configuration)
    end

    def stables
      @stables ||= Petstore::Api::Stables.new(@connection)
    end
  end
end
Steps to reproduce
$LOAD_PATH.unshift 'out/lib'
require 'petstore'

client = Petstore::Client.new(base_url: 'http://localhost')
client.stables.ponies.get(stable: 'a', pony: 'b')

Actual (ruby 3.3):

undefined method `ponies' for an instance of Petstore::Api::Stables (NoMethodError)

Expected: client.stables.ponies returns a Petstore::Api::Stables::Ponies, matching the client.<resource>.<action> shape in the generated README.

Related issues/PRs

None found.

Suggest a fix

Render the resources that are already computed, as the crystal generator does in its client.mustache (a {{#resources}} accessor on each namespace class). The api templates are written before postProcessSupportingFileData runs, so the namespace-to-resources map has to be built earlier (e.g. from resourceSegments and the paths in preprocessOpenAPI) and passed to api.mustache for the namespace class:

      def ponies
        @ponies ||= Stables::Ponies.new(@connection)
      end

For a namespace with only nested paths, the generator must still emit a namespace class (without operations) so that client.stables has something to instantiate.


Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions