dry-rb / dry-schema

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

`Dry::Schema::Compiler` cannot handle `Types::Hash.map` types #467

Open postmodern opened 1 year ago

postmodern commented 1 year ago

Describe the bug

I am trying to use a dry-type of Types::Hash.map(Types::String, Types::String) in a Dry::Validation::Contract class, however Dry:Schema::Compiler attempts to call the non-existent visit_map method.

To Reproduce

require 'dry-types'
require 'dry-validation'

module Types
  include Dry::Types()

  ScriptParams = Types::Hash.map(Types::String, Types::String)
end

class Validation < Dry::Validation::Contract

  params do
    optional(:script_params).maybe(Types::ScriptParams)
  end

end

Expected behavior

Loads and initializes the types.

Actual Result

/home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:91:in `public_send': undefined method `visit_map' for #<Dry::Schema::PredicateInferrer::Compiler:0x00007f06afa7c300 @registry=#<Dry::Schema::PredicateRegistry:0x00007f06afab8df0 @predicates=Dry::Logic::Predicates>> (NoMethodError)

          public_send(:"visit_#{meth}", rest)
          ^^^^^^^^^^^
Did you mean?  visit_sum
               visit_and
               visit_any
               visit_lax
               visit_hash
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:91:in `visit'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:138:in `visit_sum'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:91:in `public_send'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:91:in `visit'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:221:in `block in []'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/map.rb:207:in `block in fetch_or_store'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/map.rb:187:in `fetch'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/map.rb:206:in `fetch_or_store'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-core-1.0.1/lib/dry/core/cache.rb:52:in `fetch_or_store'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-types-1.7.1/lib/dry/types/predicate_inferrer.rb:220:in `[]'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema/macros/dsl.rb:238:in `extract_type_spec'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema/macros/dsl.rb:99:in `maybe'
    from test.rb:21:in `block in <class:Validation>'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema/dsl.rb:83:in `instance_eval'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema/dsl.rb:83:in `new'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema.rb:67:in `define'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-schema-1.13.3/lib/dry/schema.rb:86:in `Params'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-validation-1.10.0/lib/dry/validation/contract/class_interface.rb:217:in `define'
    from /home/postmodern/test/ruby/bundler/vendor/bundle/ruby/3.2.0/gems/dry-validation-1.10.0/lib/dry/validation/contract/class_interface.rb:54:in `params'
    from test.rb:20:in `<class:Validation>'
    from test.rb:18:in `<main>'

My environment

flash-gordon commented 1 year ago

It's not yet supported, we could throw a more meaningful error for a start. Adding support would require adding some predicates to dry-logic that we can later infer here, in dry-schema.

flash-gordon commented 1 year ago

Oh, actually, predicate_inferrer resides in dry-types

flash-gordon commented 1 year ago

I added a clean message about it to dry-types