Open ritxi opened 1 year ago
I've tested with the latest version
irb(main):008:1* schema = Dry::Schema.Params do
irb(main):009:2* required(:group).array(:hash) do
irb(main):010:2* required(:id).value(:integer)
irb(main):011:3* required(:date).filter {
irb(main):012:3* format?(%r[\d{2}/\d{2}/\d{4}])
irb(main):013:2* }.value(:date)
irb(main):014:1* end
irb(main):015:0> end
=> #<Dry::Schema::Params keys=[["group", ["id", "date"]]] rules={:group=>"key?(:group) AND key[group](array? AND each(hash? AND hash? AND set(key?(:id) AND key[id](int?), key?(:date) AND key[dat...
irb(main):016:0> schema.call(group: [{id: 1, date: '2022/05/02'}])
=> #<Dry::Schema::Result{:group=>[{:id=>1, :date=>#<Date: 2022-05-02 ((2459702j,0s,0n),+0s,2299161j)>}]} errors={} path=[]>
irb(main):017:0> require "dry/schema/version"
=> true
irb(main):018:0> Dry::Schema::VERSION
=> "1.13.0"
Confirming exact the same issue:
I have the following schema that works in isolation, but not inside an
array(:hash)
with a field with a filter that won't work
Test suite provided below
https://gist.github.com/x2es/ed6d401bd02698f48e9bf927120e0eb5
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem "dry-schema"
gem "awesome_print"
gem "minitest"
end
require 'minitest/autorun'
DocumentSchema = Dry::Schema.JSON do
optional(:date).filter(format?: /^\d{4}-\d{2}-\d{2}$/).filled(:date)
end
DocumentsSchema = Dry::Schema.JSON do
required(:documents).array(DocumentSchema)
end
module Sample
VALID_DOCUMENT = { date: "2023-01-01" }
INVALID_FORMAT = { date: "20239-01-01" }
INVALID_DATE = { date: "2023-38-01" }
FULL_LIST = {
documents: [
VALID_DOCUMENT, # 0
INVALID_FORMAT, # 1
INVALID_DATE # 2
]
}
FORMAT_LIST = {
documents: [
VALID_DOCUMENT, # 0
INVALID_FORMAT, # 1
]
}
DATE_LIST = {
documents: [
VALID_DOCUMENT, # 0
INVALID_DATE, # 1
]
}
end
class DateTest < Minitest::Test
def test_format
expected = {:date=>["is in invalid format"]}
assert_equal expected, DocumentSchema.call(Sample::INVALID_FORMAT).errors.to_h
end
def test_date
expected = {:date=>["must be a date"]}
assert_equal expected, DocumentSchema.call(Sample::INVALID_DATE).errors.to_h
end
# UNEXPECTED BEHAVIOUR
# and inconsistent with `DocumentSchema.call(Sample::INVALID_FORMAT)`
# 2) Failure:
# DateTest#test_format_list [dry_schema_array_hash_filter_issue.rb:68]:
# --- expected
# +++ actual
# @@ -1 +1 @@
# -{:documents=>{1=>{:date=>["is in invalid format"]}}}
# +{}
def test_format_list
expected = {:documents=>{1=>{:date=>["is in invalid format"]}}}
assert_equal expected, DocumentsSchema.call(Sample::FORMAT_LIST).errors.to_h
end
def test_date_list
expected = {:documents=>{1=>{:date=>["must be a date"]}}}
assert_equal expected, DocumentsSchema.call(Sample::DATE_LIST).errors.to_h
end
# 1) Failure:
# DateTest#test_full_list [dry_schema_array_hash_filter_issue.rb:83]:
# --- expected
# +++ actual
# @@ -1 +1 @@
# -{:documents=>{1=>{:date=>["is in invalid format"]}, 2=>{:date=>["must be a date"]}}}
# +{:documents=>{1=>{:date=>["must be a date"]}}}
def test_full_list
expected = {
:documents=>{
1=>{:date=>["is in invalid format"]},
2=>{:date=>["must be a date"]}
}
}
assert_equal(expected, DocumentsSchema.call(Sample::DATE_LIST).errors.to_h)
end
end
# {
# :full_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, # {:date=>#<Date: 20239-01-01 ((9113203j,0s,0n),+0s,2299161j)>}, {:date=>"2023-38-01"}]} errors={:documents=>{2=># {:date=>["must be a date"]}}} path=[]>,
# :format_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, {:date=>#<Date: 20239-01-01 ((9113203j,0s,0n),+0s,2299161j)>}]} errors={} path=# []>,
# :date_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, {:date=>"2023-38-01"}]} errors={:documents=>{1=>{:date=>["must be a date"]}}} path=[]>,
# :format => #<Dry::Schema::Result{:date=>"20239-01-01"} errors={:date=>["is in invalid format"]} path=[]>,
# :date => #<Dry::Schema::Result{:date=>"2023-38-01"} errors={:date=>["must be a date"]} path=[]>
# }
ap ({
full_list: DocumentsSchema.call(Sample::FULL_LIST),
format_list: DocumentsSchema.call(Sample::FORMAT_LIST),
date_list: DocumentsSchema.call(Sample::DATE_LIST),
format: DocumentSchema.call(Sample::INVALID_FORMAT),
date: DocumentSchema.call(Sample::INVALID_DATE)
})
DocumentSchema.call(Sample::INVALID_FORMAT)
expected to be consistent with DocumentsSchema.call(Sample::FORMAT_LIST)
:
Pay attention to :format
, :format_list
and :full_list
outputs
{
:full_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, {:date=>#<Date: 20239-01-01 ((9113203j,0s,0n),+0s,2299161j)>}, {:date=>"2023-38-01"}]} errors={:documents=>{2=>{:date=>["must be a date"]}}} path=[]>,
:format_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, {:date=>#<Date: 20239-01-01 ((9113203j,0s,0n),+0s,2299161j)>}]} errors={} path=[]>,
:date_list => #<Dry::Schema::Result{:documents=>[{:date=>#<Date: 2023-01-01 ((2459946j,0s,0n),+0s,2299161j)>}, {:date=>"2023-38-01"}]} errors={:documents=>{1=>{:date=>["must be a date"]}}} path=[]>,
:format => #<Dry::Schema::Result{:date=>"20239-01-01"} errors={:date=>["is in invalid format"]} path=[]>,
:date => #<Dry::Schema::Result{:date=>"2023-38-01"} errors={:date=>["must be a date"]} path=[]>
}
Run options: --seed 58415
# Running:
F..F.
Finished in 0.007960s, 628.1263 runs/s, 628.1263 assertions/s.
1) Failure:
DateTest#test_full_list [dry_schema_array_hash_filter_issue.rb:83]:
--- expected
+++ actual
@@ -1 +1 @@
-{:documents=>{1=>{:date=>["is in invalid format"]}, 2=>{:date=>["must be a date"]}}}
+{:documents=>{1=>{:date=>["must be a date"]}}}
2) Failure:
DateTest#test_format_list [dry_schema_array_hash_filter_issue.rb:68]:
--- expected
+++ actual
@@ -1 +1 @@
-{:documents=>{1=>{:date=>["is in invalid format"]}}}
+{}
5 runs, 5 assertions, 2 failures, 0 errors, 0 skips
Describe the bug
I have the following schema that works in isolation, but not inside an
array(:hash)
with a required field with a filter that won't workTo Reproduce
Expected behavior
I expect filter validation to work
My environment