Skip to content

Conversation

@baweaver
Copy link
Contributor

Adds a .description(text) method to schema key definitions that stores descriptions in type
metadata and includes them in JSON schema output.

Usage

schema = Dry::Schema.define do
  required(:first_name).filled(:string).description("First name of the user")
  optional(:age).filled(:integer).description("Age of the user")
  required(:address).description("The shipping address").hash do
    required(:street).filled(:string).description("Street address")
    optional(:city).filled(:string).description("City name")
  end
end

# Access via type metadata
schema.types[:first_name].meta[:description]
# => "First name of the user"

# Included in JSON schema output
Dry::Schema.load_extensions(:json_schema)
schema.json_schema[:properties][:first_name][:description]
# => "First name of the user"

Implementation

• Descriptions stored in type metadata (:description key)
• Works with all macro types (required, optional, filled, maybe, hash, array, etc.)
• Preserved when types are replaced during macro chaining
• JSON schema compiler extracts descriptions from type metadata for both top-level and nested
keys
• Improved set_type to preserve all incoming type metadata, not just schema-specific meta

Changes

lib/dry/schema/macros/dsl.rb - Added description method
lib/dry/schema/dsl.rb - Updated set_type to preserve type metadata
lib/dry/schema/extensions/json_schema.rb - Pass types to compiler
lib/dry/schema/extensions/json_schema/schema_compiler.rb - Extract and include descriptions
spec/integration/schema/description_spec.rb - Test coverage

Backwards compatible with existing schemas.

- Add description() method to Macros::DSL for setting field descriptions
- Store descriptions in type metadata
- Preserve descriptions when types are replaced during macro chaining
- Include descriptions in JSON schema output via json_schema extension
- Support nested schema descriptions
# @api public
def json_schema(loose: false)
compiler = SchemaCompiler.new(root: true, loose: loose)
compiler = SchemaCompiler.new(root: true, loose: loose, types: types)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to pipe types down as those are where most of the meta / description info lives.

- Simplify description method in macros/dsl.rb
- Extract current_meta variable in json_schema compiler
- Reformat visit_set method for clarity
Copy link
Member

@timriley timriley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good to me! Thank you @baweaver.

I've left just one question for you, which I think would be good to address before merging.

@flash-gordon Do you have any thoughts about this one?


current_meta = @types[name]&.meta

new_meta[:description] ||= current_meta[:description] if current_meta&.key?(:description)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get why this is here. It's so you can have a line like this, where the real type for the key doesn't get set until after the description is given:

required(:first_name).description("First name of the user").filled(:string)

This is a good thing! But it's also the only special-cased line in this method.

It feels like it at least warrants a comment explaining why it is so. Reckon you could add one?

(In fact, I wonder if there is a way to generalise it?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified and generalized to merge a wider range of metadata, added comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @baweaver, that’s very nice!

- Extract metadata preservation logic into dedicated method
- Preserve all user-defined metadata (not just description)
- Clearly separate system-managed keys from user-defined keys
- Add comprehensive documentation explaining fluent API enablement
- All tests passing (3226 examples, 0 failures)
@flash-gordon
Copy link
Member

This looks like a reasonable improvement of the DSL. Should we, though, add #description in the JSON schema extension rather than the general DSL? The fact that you can call .description, which does nothing when json_schema is not loaded can be confusing

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.

4 participants