require 'dry/validation' | |
require 'dry/types' | |
require 'dry/struct' | |
module Types | |
include Dry::Types() | |
end | |
class OrderContract < Dry::Validation::Contract | |
params do | |
required(:discount).value(:integer) | |
required(:line_items).array(:hash) do | |
required(:quantity).value(:integer) | |
required(:code).value(:string) | |
end | |
end | |
rule(:line_items) do | |
values[:line_items].each_with_index do |item, idx| | |
key([:line_items, idx]).failure('quantity must be 1') if item[:quantity] != 1 && item[:code] == 'ABC' | |
end | |
end | |
end | |
class LineItem < Dry::Struct | |
attribute :quantity, Types::Integer | |
attribute :code, Types::String | |
end | |
class Order < Dry::Struct | |
attribute :discount, Types::Integer | |
attribute :line_items, Types::Array.of(LineItem) | |
end | |
contract = OrderContract.new | |
data = { | |
discount: 4, | |
line_items: [ | |
{ quantity: 2, code: 'FOO' }, | |
{ quantity: 3, code: 'ABC' }, | |
{ quantity: 4, code: 'BAR' } | |
] | |
} | |
result = contract.(data) | |
puts result.errors.to_h.inspect | |
# {:line_items=>{1=>["quantity must be 1"]}} | |
data = { | |
discount: 4, | |
line_items: [ | |
{ quantity: 2, code: 'FOO' }, | |
{ quantity: 1, code: 'ABC' }, | |
{ quantity: 4, code: 'BAR' } | |
] | |
} | |
result = contract.(data) | |
puts result.errors.to_h.inspect | |
# {} | |
order = Order.new(data) | |
puts order.inspect | |
# #<Order discount=4 line_items=[#<LineItem quantity=2 code="FOO">, #<LineItem quantity=1 code="ABC">, #<LineItem quantity=4 code="BAR">]> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment