dry-schema: Undefined method `visit_constructor' for custom Hash constructor

Describe the bug:

It may be a regression, or an undocumented syntax change. I’m trying to coerce a JSON string param into a hash through a custom constructor. It worked in 1.4.3 but now fails in 1.5.0.

The corresponding versions of dry-types pulled in by dry-schema were 1.2.2 and 1.4.0 respectively.

To Reproduce:

require 'dry-schema'
require 'dry-types'
require 'json'

module Types
  include Dry.Types()
  JSONHash = Types::Hash.constructor do |h|
    h.is_a?(::Hash) ? h : ::JSON.parse(h)
  end
end

Schema = Dry::Schema.Params do
  required(:foo).filled(Types::JSONHash)
end

h = Schema.call(foo: %q({ "hello": "hi" })).to_h
puts "#{h[:foo].class.name} -- #{h[:foo].inspect}"

With dry-schema 1.4.3, here’s the output

Hash -- {"hello"=>"hi"}

With dry-schema 1.5.0, I get this:

...
undefined method `visit_constructor' for #<Dry::Schema::Compiler:0x00007fc2ba917858> (NoMethodError)
Did you mean?  visit_attr

Expected behavior

Behavior described above for 1.4.3 seems correct.

Your environment

  • Affects my production application: YES
  • Ruby version: ruby 2.7.1p83
  • macOS Catalina

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 7
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

So, like I mentioned a little…over…a year…ago…this was caused by the fact that a custom type would not be set in various cases. I gave it a shot to see if at least the scenarios mentioned in this issue can be addressed and I succeeded. I’m not too confident that this issue will go away 100% so I’ll revisit this when working on 2.0.0.

For now, this specific issue (as in, the scenarios mentioned here) will be addressed in the upcoming 1.7.0 release.

oh noez! 😕 thanks for the report, I’ll fix it in 1.5.1

@solnic Great news! Thank you for the fix.

If I can follow the code, I would help with the issue; but I can’t read the dry-rb code at all. Probably the issue is on me, or dry-rb might used too many Ruby features.

@midnight-wonderer don’t worry about this, you jumped into literally one of the most complicated codebases in dry-rb land 🙂 The schema DSL has a lot of additional complexity because it still works with or without type specifications and this will be greatly simplified in 2.0.0 (if I had a penny every time I mention this…lol). Furthermore, debugging issues with types also requires knowledge about dry-types and that’s a journey on its own. Then if you want to understand how predicates are handled, you’d need to understand dry-logic first.

If you take a look at the PR where I addressed the issue, you’ll see that it was a one-file change. The trick is to know where to look 🙂

@solnic sure, it’s on the surface. Fixing this particular error shouldn’t be a problem, but I didn’t try. My concern is I saw a more substantial problem with constructors and schemas, but I don’t remember what that was 😕