Skip to content

fix(ruby): generate from_json!/from_dynamic! helpers for top-level enums#3047

Open
schani wants to merge 6 commits into
masterfrom
agent/fix-issue-724
Open

fix(ruby): generate from_json!/from_dynamic! helpers for top-level enums#3047
schani wants to merge 6 commits into
masterfrom
agent/fix-issue-724

Conversation

@schani

@schani schani commented Jul 20, 2026

Copy link
Copy Markdown
Member

Bug

For a top-level JSON Schema enum, quicktype's Ruby target emitted a
leading usage comment claiming:

#   top_level_enum = TopLevelEnum.from_json! "…"
#   puts top_level_enum == TopLevelEnum::One

but TopLevelEnum was generated as a plain Ruby module of string
constants with no from_json! (or from_dynamic!) method defined on
it. Following the comment's instructions would raise
NoMethodError: undefined method 'from_json!' for TopLevelEnum.

Repro:

node dist/index.js --lang ruby --src-lang schema test/inputs/schema/top-level-enum.schema

Root cause

RubyRenderer#emitClass and RubyRenderer#emitUnion both emit a
def self.from_json!(json) (backed by from_dynamic!) directly on the
generated class, so the shared leading comment (emitted once in
emitSourceStructure) is accurate for those. RubyRenderer#emitEnum,
however, only emitted the constant table and never defined those
helper methods, so the same comment was misleading for top-level enums.

This was a known gap — test/languages.ts had top-level-enum.schema
in Ruby's skipSchema list with the comment "We don't generate a
convenience method for top-level enums".

Fix

RubyRenderer#emitEnum now also emits from_dynamic!/from_json!
class methods on the enum module (skipped under --just-types, same
as the class/union renderers), reusing the Types::<EnumName> dry-types
validator that was already being emitted:

module TopLevelEnum
  One   = "one"
  Three = "three"
  Two   = "two"

  def self.from_dynamic!(d)
    Types::TopLevelEnum[d]
  end

  def self.from_json!(json)
    from_dynamic!(JSON.parse(json))
  end
end

This makes the generated code match the leading usage comment for
top-level enums, the same way it already did for classes and unions.

Test coverage

top-level-enum.schema is no longer skipped for the Ruby target in
test/languages.ts (the skipSchema entry and its now-outdated
comment were removed), so this is now covered end-to-end by the
existing test/inputs/schema/top-level-enum.schema /
.1.json JSON Schema fixture via FIXTURE=schema-ruby, per the
repo's fixture-testing conventions.

Verification

  • npm run build passes.
  • npx vitest run test/unit: 170/170 tests pass.
  • QUICKTEST=true FIXTURE=schema-ruby script/test test/inputs/schema/top-level-enum.schema passes end-to-end (previously skipped, now generates, round-trips, and validates correctly via the Ruby driver).
  • Re-ran the exact repro command: the emitted Ruby code now defines from_dynamic!/from_json! on TopLevelEnum, matching the leading comment.
  • Ran the broader schema-ruby fixture suite: found 3 pre-existing failures (tuple.schema, union-list.schema, union-int-double.schema) unrelated to this change — verified by reproducing the identical failures on unfixed master (same Dry::Types::CoercionError / "can't convert Symbol into Hash" already documented elsewhere in test/languages.ts as "Ruby union code does not work with new Dry"). No new failures were introduced.
  • CI will run the full fixture matrix, including the newly-enabled schema-ruby case for top-level-enum.schema.

Fixes #724

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Generated-output differences

1 files differ — 0 modified, 1 new, 0 deleted
34 changed lines — +34 / −0

Open the generated-output report →

@schani

schani commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

The PR description says that the problem only happens for top-level enums, but this is emitting those methods for all types, not just enums! Fix that!

@github-actions

Copy link
Copy Markdown

Generated-output differences

1 files differ — 0 modified, 1 new, 0 deleted
34 changed lines — +34 / −0

Open the generated-output report →

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generate correct comment for Ruby top-level enum

1 participant