Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent behavior when passing array schema to a property #345

Open
lenart opened this issue Mar 3, 2021 · 1 comment
Open

Inconsistent behavior when passing array schema to a property #345

lenart opened this issue Mar 3, 2021 · 1 comment

Comments

@lenart
Copy link

lenart commented Mar 3, 2021

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)
@solnic
Copy link
Member

solnic commented Mar 4, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants