Skip to content

Instantly share code, notes, and snippets.

@fnordfish
Last active June 28, 2018 10:19
Show Gist options
  • Save fnordfish/9037fcd39b855e181f4a40ca031462ee to your computer and use it in GitHub Desktop.
Save fnordfish/9037fcd39b855e181f4a40ca031462ee to your computer and use it in GitHub Desktop.
Trailblazer Operation without Reform contracts for sync
require "pp"
require "reform" # that's what we want to get rid of
require "dry-validation"
require "trailblazer"
require "trailblazer/operation"
# For the sake of this sample, the "model" class is a bit simple
Customer = Hash
# The storage isn't very sophisticated either
Store = []
module Types
require "dry-types"
require "ipaddr"
include Dry::Types.module
Ip = Types.Constructor(::IPAddr) do |input|
::IPAddr.new(input) if input && !input.empty?
end
end
module Concepts
module Customer
CreateSchema = Dry::Validation.Form do
configure do
config.type_specs = true
end
required(:name, :string).filled
optional(:address, :string)
optional(:ip, Types::Ip).maybe(type?: ::IPAddr)
end
class Create < Trailblazer::Operation
class Present < Trailblazer::Operation
step Model(::Customer, :new)
end
extend Contract::DSL
contract :default, CreateSchema
step Nested(Present)
# These two steps should be merged into one
step self::Contract::Validate(name: :default, key: :customer)
step ->(options, params:, model:, **) {
params[:customer] = options["result.contract.default"].output
}
step :sync!
step :save!
def sync!(options, params:, model:, **)
model.merge!(params)
end
def save!(options, model:, **)
Store << model
end
end
end
end
pp Concepts::Customer::Create.(customer: {name: "Fred"})["model"]
# {:name=>"Fred"}
pp Concepts::Customer::Create.(customer: {name: "Fred", non_validated_key: "doesn't sync", address: "Long rd. 5"})["model"]
# {:name=>"Fred", :address=>"Long rd. 5"}
pp Concepts::Customer::Create.(customer: {name: "Fred", ip: "8.8.8.8"})["model"]
# {:name=>"Fred", :ip=>#<IPAddr: IPv4:8.8.8.8/255.255.255.255>}
res = Concepts::Customer::Create.(customer: {name: "Fred", ip: "not-an-ip"})
pp res.success?, res["model"]
# false
# {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment