From ca16f297c51a816e522a179c7631e994275ca1b6 Mon Sep 17 00:00:00 2001 From: Santiago Doldan Date: Tue, 7 Nov 2023 16:51:11 -0300 Subject: [PATCH] Fix info extension for maybe macro --- .../schema/extensions/info/schema_compiler.rb | 16 ++++++++++--- spec/extensions/info/schema_spec.rb | 24 +++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/dry/schema/extensions/info/schema_compiler.rb b/lib/dry/schema/extensions/info/schema_compiler.rb index c497873c..108b46d5 100644 --- a/lib/dry/schema/extensions/info/schema_compiler.rb +++ b/lib/dry/schema/extensions/info/schema_compiler.rb @@ -71,7 +71,7 @@ def visit_and(node, opts = EMPTY_HASH) # @api private def visit_implication(node, opts = EMPTY_HASH) node.each do |el| - visit(el, opts.merge(required: false)) + visit(el, opts.merge(required: false, nullable: false)) end end @@ -83,7 +83,14 @@ def visit_each(node, opts = EMPTY_HASH) # @api private def visit_key(node, opts = EMPTY_HASH) name, rest = node - visit(rest, opts.merge(key: name, required: true)) + visit(rest, opts.merge(key: name, required: true, nullable: false)) + end + + # @api private + def visit_not(_node, opts = EMPTY_HASH) + key = opts[:key] + + keys[key][:nullable] = true end # @api private @@ -93,7 +100,10 @@ def visit_predicate(node, opts = EMPTY_HASH) key = opts[:key] if name.equal?(:key?) - keys[rest[0][1]] = {required: opts.fetch(:required, true)} + required = opts.fetch(:required, true) + nullable = opts.fetch(:nullable, false) + + keys[rest[0][1]] = {required: required, nullable: nullable} else type = PREDICATE_TO_TYPE[name] assign_type(key, type) if type diff --git a/spec/extensions/info/schema_spec.rb b/spec/extensions/info/schema_spec.rb index 840d084e..c33b8958 100644 --- a/spec/extensions/info/schema_spec.rb +++ b/spec/extensions/info/schema_spec.rb @@ -8,7 +8,7 @@ subject(:schema) do Dry::Schema.JSON do required(:email).filled(:string) - optional(:age).filled(:integer) + optional(:age).maybe(:integer) required(:roles).array(:hash) do required(:name).filled(:string) @@ -17,9 +17,9 @@ optional(:address).hash do required(:street).filled(:string) - required(:zipcode).filled(:string) + optional(:zipcode).filled(:string) required(:city).filled(:string) - optional(:phone).filled(:string) + optional(:phone).maybe(:string) end end end @@ -28,23 +28,28 @@ { keys: { email: { + nullable: false, required: true, type: "string" }, age: { + nullable: true, required: false, type: "integer" }, roles: { + nullable: false, required: true, type: "array", member: { keys: { name: { + nullable: false, required: true, type: "string" }, desc: { + nullable: false, required: false, type: "string" } @@ -52,22 +57,27 @@ } }, address: { + nullable: false, required: false, type: "hash", keys: { street: { + nullable: false, required: true, type: "string" }, zipcode: { - required: true, + nullable: false, + required: false, type: "string" }, city: { + nullable: false, required: true, type: "string" }, phone: { + nullable: true, required: false, type: "string" } @@ -95,20 +105,24 @@ { keys: { opt1: { + nullable: false, required: true, type: "array" }, opt2: { + nullable: false, required: true, type: "array", member: "string" }, opt3: { + nullable: false, required: true, type: "array", member: "integer" }, opt4: { + nullable: false, required: true, type: "array", member: "bool" @@ -136,7 +150,7 @@ }.each do |type_spec, type_name| it "infers '#{type_name}' from '#{type_spec}'" do expect(Dry::Schema.define { required(:key).value(type_spec) }.info).to eql( - keys: {key: {required: true, type: type_name}} + keys: {key: {nullable: false, required: true, type: type_name}} ) end end