I’m trying to support a “polymorphic” schema for sub-hashes using dry-validation.
I couldn’t find any documentation on this capability, and I ended up hacking something together that seems… ugly.
There has got to be a better way to do this.
require 'dry-validation'
class ParentContract < Dry::Validation::Contract
json do
optional(:child).hash
end
rule :child do
case value[:type]
when 'special'
child_contract = SpecialChildContract.new
else
child_contract = ChildContract.new
end
child_contract.call(value).errors.each do |message|
body = message.meta.empty? ? message.text : {text: message.text, meta: message.meta}
key([:child] + message.path).failure(body)
end
end
end
class ChildContract < Dry::Validation::Contract
json do
required(:type).value(:string)
required(:name).value(:string)
optional(:description).value(:string)
end
end
class SpecialChildContract < ChildContract
json do
required(:foobar).value(:string)
end
end
c1 = ChildContract.new
p c1.call(type: 'generic', name: 'abc').errors.to_h
c2 = SpecialChildContract.new
p c2.call(type: 'special', name: 'abc', description: 1234).errors.to_h
h = ParentContract.new
p h.call(child: { type: 'special', name: 'abc', description: 1234}).errors.to_h