dry-rb / dry-schema

Coercion and validation for data structures
https://dry-rb.org/gems/dry-schema
MIT License
422 stars 110 forks source link

Different validation result while using strings vs symbols as keys #381

Closed dawlib closed 2 years ago

dawlib commented 2 years ago

Describe the bug

There is a different result of validation while using string-type keys and while using symbol-type keys in the input object passed for validating.

To Reproduce

require 'dry/schema'

module Types
  include Dry::Types()
end

class MyItem < Dry::Schema::JSON
  define do
    required(:name).filled(Types::String.enum(*%w[b]))
    optional(:time).filled(:time)
  end
end

class MyList < Dry::Schema::JSON
  define do
    required(:list).value(:array).each { MyItem.new }
  end
end

item1 = { 'name' => 'b', 'time' => Time.now.iso8601 }
item2 = { name: 'b', time: Time.now.iso8601 }

MyItem.new.call(item1).failure? # => false
MyItem.new.call(item2).failure? # => false
MyList.new.call('list' => [item1]).failure? # => true
MyList.new.call('list' => [item1])
# => #<Dry::Schema::Result{:list=>[{"name"=>"b", "time"=>"2021-11-16T14:47:11+01:00"}]} errors={:list=>{0=>{:name=>["is missing"]}}} path=[]>
MyList.new.call('list' => [item2]).failure? # => true
MyList.new.call('list' => [item2])
# => #<Dry::Schema::Result{:list=>[{:name=>"b", :time=>"2021-11-16T14:47:11+01:00"}]} errors={:list=>{0=>{:time=>["must be a time"]}}} path=[]>
MyList.new.call('list' => [item1, item2])
# => #<Dry::Schema::Result{:list=>[{"name"=>"b", "time"=>"2021-11-16T14:47:11+01:00"}, {:name=>"b", :time=>"2021-11-16T14:47:11+01:00"}]} errors={:list=>{0=>{:name=>["is missing"]}, 1=>{:time=>["must be a time"]}}} path=[]>

Expected behavior

I would expect to receive a proper result of validation while executing the commands below:

MyList.new.call('list' => [item1]).failure? # => false
MyList.new.call('list' => [item1]) # no errors in the retured object
MyList.new.call('list' => [item2]).failure? # => false
MyList.new.call('list' => [item2]) # no errors in the retured object
MyList.new.call('list' => [item1, item2]) # no errors in the returned object

My environment

dawlib commented 2 years ago

I just found out that this is expected and we must provide the string-type keys.