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
- Fix handling of constructor types Fixes #280 — committed to dry-rb/dry-schema by solnic 3 years ago
- Merge pull request #365 from dry-rb/280-fix-handling-of-constructor-types [changelog] fixed: "Using constructor types should work fine now ie `required(:foo).filled(Types::Params::Integer.construc... — committed to dry-rb/dry-schema by solnic 3 years ago
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.
@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 😕