Skip to content

Instantly share code, notes, and snippets.

@solnic
Last active May 7, 2019 15:05
Show Gist options
  • Save solnic/5ee0a24b688af87ae23cec4384e33ab0 to your computer and use it in GitHub Desktop.
Save solnic/5ee0a24b688af87ae23cec4384e33ab0 to your computer and use it in GitHub Desktop.
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