Emit the entity named by a String using:

What does this MR do and why?

A String using: (for example expose :owner, using: 'Entities::Owner') wrote a $ref but never converted the entity it names: register_nested_entity skipped anything that was not a Class. Unless something else reached that entity, the document pointed at a component that did not exist.

EntityConverter#nested_entity_class now resolves a String with Object.const_get, which is what grape-entity's constantize does when it renders. Everything downstream then sees a class, so the String form is referenced, registered, and inlined for merge: true exactly like the class form.

A String that names no class resolves to nil, so the exposure becomes a plain property instead of a dangling $ref. With config.warnings enabled it also prints one line, for example:

[gitlab-grape-openapi] unresolved using: Entities::Project#owner using="Entities::Ownr"

The deviation (#9) requirement in openspec/specs/entity-schemas/spec.md moves to implemented, and the README's warnings row mentions the new warning.

Closes #9

Does gitlab-org/gitlab's generated openapi_v3.yaml change?

No. As noted on the issue, lib/api and ee/lib/api have no String-form using:.

How was this tested?

  • New examples cover a String naming a real entity (plain and is_array, plus registration), a String naming no class (plain property, with and without config.warnings), and merge: true with a String. They fail without the lib/ change.
  • The previous "namespaced entity" example asserted the dangling $ref for 'Hello::World::Human', so it now asserts the plain-property behaviour.
  • bundle exec rspec: everything passes except the 2 ActiveSupport::TimeWithZone default examples, which fail identically on main on my Windows machine because it has no zoneinfo directory.
  • bundle exec rubocop: no offenses.

🤖 Generated with Claude Code

Merge request reports

Loading
Loading