dry-rb / dry-rb/dry-validation

Inconsistent behavior in nested schemas via passed in blocks

Open
#703 8 comments 0 reactions 0 assignees View on GitHub
bug help wanted
Dominant language
Ruby
Stars
1.4k
Forks
195
PR merge metrics
No merged PRs in 30d

Description

## Describe the bug

When schemas are passed blocks, `required` field behavior does not always work, and there is inconsistent behavior for reaching validation rules -- although it seems to correlate with whether the `required` is evaluated.

## To Reproduce

```
class TireSchema < Dry::Schema::JSON
define do
optional(:tread).value(:string, included_in?: %w(offroad allterrain sport road))
optional(:size).value(:integer)
end
end

class SportsCarSchema < Dry::Schema::JSON
define do
optional(:recommended_tire).hash.schema(TireSchema.new) do
optional(:tread).value(:string, included_in?: %w(sport road))
end
end
end

class RaceDriverContract < Dry::Validation::Contract
rule('car.recommended_tire.size') do
puts "The runtime made it to the rule!"
end

json do
required(:car).hash.schema(SportsCarSchema.new) do
required(:recommended_tire).hash.schema(TireSchema.new) do
required(:size).value(:integer)
end
end
end
end

contract = RaceDriverContract.new

contract.call({ car: { recommended_tire: { tread: "invalid value" } } })
# The runtime made it to the rule!
# => #{:recommended_tire=>{:tread=>"invalid value"}}} errors={:car=>{:recommended_tire=>{:tread=>["must be one of: offroad, allterrain, sport, road"]}}}>

contract.call({ car: { recommended_tire: { tread: "sport" } } })
# => #{:recommended_tire=>{:tread=>"sport"}}} errors={:car=>{:recommended_tire=>{:size=>["is missing"]}}}>

contract.call({ car: { recommended_tire: { tread: "allterrain" } } })
# The runtime made it to the rule!
# => #{:recommended_tire=>{:tread=>"allterrain"}}} errors={:car=>{:recommended_tire=>{:tread=>["must be one of: sport, road"]}}}>
```

## Expected behavior

I would expect every one of the above results to contain ```{:recommended_tire=>{:size=>["is missing"]}```, and I would either expect all of them to make it to the rule or none of them to make it to the rule.

## My environment

- Affects my production application: YES
- Ruby version: 2.7.2
- OS: macOS 12.0.1 21A559

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.