dry-schema
dry-schema copied to clipboard
Inconsistent behavior when passing array schema to a property
Describe the bug
There's an inconsistency that leads to some unexpected behavior when using nested schemas. The problem is best described by the example below.
To Reproduce & Expected behavior
FriendSchema = Dry::Schema.Params do
optional(:nickname).filled(:string)
end
class UserSchema < Dry::Validation::Contract
params do
optional(:name)
optional(:close_friends).maybe(:array, FriendSchema)
optional(:friends).maybe do
array(FriendSchema)
end
end
end
UserSchema.new.call({name: "John", friends: []}) # works
UserSchema.new.call({name: "John", close_friends: []}) # expects to work but does not
NoMethodError: undefined method `key?' for []:Array
from /Users/lenart/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/dry-logic-1.1.0/lib/dry/logic/predicates.rb:25:in `key?'
If filled(:string) is omitted from FriendSchema the error goes away but in that case, all params get through.
FriendSchema = Dry::Schema.Params do
optional(:nickname)
end
# UserSchema same as in above example
UserSchema.new.call({name: "John", close_friends: [{any: 'value'}]})
# expected {name: "John"}
# actual {name: "John", close_friends: [{any: "value"}]}
UserSchema.new.call({name: "John", friends: [{any: 'value'}]})
# returns as expected {name: "John", friends: [{}]}
I'm not sure that the empty object is what I'd expect in the friends array.
The same syntax seems to work fine when dealing with hashes (instead of arrays).
FriendSchema = Dry::Schema.Params do
optional(:nickname).filled(:string)
end
class UserSchema < Dry::Validation::Contract
params do
optional(:name)
optional(:close_friends).maybe(:hash, FriendSchema)
optional(:friends).maybe do
hash(FriendSchema)
end
end
end
UserSchema.new.call({name: "John", close_friends: {any: 'value'}})
# returns as expected {name: "John", close_friends: {}}
UserSchema.new.call({name: "John", friends: {any: 'value'}})
# returns as expected {name: "John", friends: {}}
My environment
- Affects my production application: NO
- Ruby version: 2.6.6
- OS: MacOS Big Sur 11.2.1
- dry-schema 1.6.1
other related gems in Gemfile.lock
dry-configurable (0.12.1)
dry-container (0.7.2)
dry-core (0.5.0)
dry-equalizer (0.3.0)
dry-inflector (0.2.0)
dry-initializer (3.0.4)
dry-logic (1.1.0)
dry-schema (1.6.1)
dry-transformer (0.1.1)
dry-types (1.5.1)
dry-validation (1.6.0)
I assigned it to 2.0.0 because all DSL inconsistencies will be easier to address after a couple of improvements/refactorings are done, and they are scheduled for 2.0.0.