Skip to content

Commit

Permalink
Support for Maybe macro in info extension (close #471)
Browse files Browse the repository at this point in the history
Co-Authored-By: Santiago Doldán <[email protected]>
  • Loading branch information
flash-gordon and santiagodoldan committed Jan 6, 2025
1 parent 15d26d4 commit 56fc4e3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 16 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ group :test do
gem "i18n", require: false
gem "json-schema"
gem "ostruct"
gem "super_diff"
gem "transproc"
end

Expand Down
23 changes: 16 additions & 7 deletions lib/dry/schema/extensions/info/schema_compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,25 @@ 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))
case node
in [:not, [:predicate, [:nil?, _]]], el
visit(el, {**opts, nullable: true})
else
node.each do |el|
visit(el, {**opts, required: false})
end
end
end

# @api private
def visit_each(node, opts = EMPTY_HASH)
visit(node, opts.merge(member: true))
visit(node, {**opts, member: true})
end

# @api private
def visit_key(node, opts = EMPTY_HASH)
name, rest = node
visit(rest, opts.merge(key: name, required: true))
visit(rest, {**opts, key: name, required: true})
end

# @api private
Expand All @@ -93,19 +98,23 @@ def visit_predicate(node, opts = EMPTY_HASH)
key = opts[:key]

if name.equal?(:key?)
keys[rest[0][1]] = {required: opts.fetch(:required, true)}
keys[rest[0][1]] = {
required: opts.fetch(:required, true)
}
else
type = PREDICATE_TO_TYPE[name]
assign_type(key, type) if type
nullable = opts.fetch(:nullable, false)
assign_type(key, type, nullable) if type
end
end

# @api private
def assign_type(key, type)
def assign_type(key, type, nullable)
if keys[key][:type]
keys[key][:member] = type
else
keys[key][:type] = type
keys[key][:nullable] = nullable
end
end
end
Expand Down
39 changes: 30 additions & 9 deletions spec/extensions/info/schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
required(:street).filled(:string)
required(:zipcode).filled(:string)
required(:city).filled(:string)
optional(:phone).filled(:string)
optional(:phone).maybe(:string)
end
end
end
Expand All @@ -29,47 +29,57 @@
keys: {
email: {
required: true,
nullable: false,
type: "string"
},
age: {
required: false,
nullable: false,
type: "integer"
},
roles: {
required: true,
type: "array",
nullable: false,
member: {
keys: {
name: {
required: true,
type: "string"
type: "string",
nullable: false
},
desc: {
required: false,
type: "string"
type: "string",
nullable: false
}
}
}
},
address: {
required: false,
type: "hash",
nullable: false,
keys: {
street: {
required: true,
type: "string"
type: "string",
nullable: false
},
zipcode: {
required: true,
type: "string"
type: "string",
nullable: false
},
city: {
required: true,
type: "string"
type: "string",
nullable: false
},
phone: {
required: false,
type: "string"
type: "string",
nullable: true
}
}
}
Expand All @@ -88,6 +98,7 @@
required(:opt2).filled(Types::Array(:string))
required(:opt3).filled(Types::Array(:integer))
required(:opt4).filled(Types::Array(:bool))
required(:opt5).maybe(Types::Array(:bool))
end
end

Expand All @@ -96,21 +107,31 @@
keys: {
opt1: {
required: true,
type: "array"
type: "array",
nullable: false
},
opt2: {
required: true,
type: "array",
nullable: false,
member: "string"
},
opt3: {
required: true,
type: "array",
nullable: false,
member: "integer"
},
opt4: {
required: true,
type: "array",
nullable: false,
member: "bool"
},
opt5: {
required: true,
type: "array",
nullable: true,
member: "bool"
}
}
Expand All @@ -136,7 +157,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: {required: true, nullable: false, type: type_name}}
)
end
end
Expand Down
4 changes: 4 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
Dir[SPEC_ROOT.join("shared/**/*.rb")].each(&method(:require))
Dir[SPEC_ROOT.join("support/**/*.rb")].each(&method(:require))

Warning.ignore(%r{rspec/matchers})

require "super_diff/rspec"

require "dry/schema"
require "dry/types"

Expand Down

0 comments on commit 56fc4e3

Please sign in to comment.