Closed sbezugliy closed 1 year ago
The same for interactor setting default value as next
# frozen_string_literal: true
require "base64"
module Interactors
module Base64
class EncodeInteractor < Dry::Validation::Contract
extend Dry::Initializer
include Dry::Transaction
schema Schemas::Base64::DataSchema
param :data, default: proc { "" }
step :encode
private
def encode(input)
Success(cypher: ::Base64.encode64(input[:data]))
end
end
end
end
Transaction and Contract are not meant to be used in the same class, I'm not sure if this causes the issue but I figured I should mention that. Both implement #call
so this doesn't make sense.
Hmm... Understood. I did find this as interesting use-case, mixing both inside of same context. I will analyze one more time, to combine them, due to I want to get thin context between serializers and backend classes, and to realise conveyor and railway approaches, with strong fault traceability.
Or I will extract validators to additional layer, but wanted to make smaller count of levels. Also I don't use models, but only backend classes and libs, so implementation of validators at the level of contracts/interactors have sense for current case.
And thank you for direction to solve!
Solved it in this way.
schema:
# frozen_string_literal: true
module Schemas
module Base64
DataSchema = Dry::Schema.Params do
required(:data).filled(:string)
end
end
end
contracts:
module Contracts
class BaseContract < Dry::Validation::Contract
include Dry::Logic
include Dry::Monads[:result]
Dry::Validation.load_extensions :monads
end
end
# frozen_string_literal: true
module Contracts
module Base64
class EncodeContract < BaseContract
schema Schemas::Base64::DataSchema
end
end
end
interactor:
# frozen_string_literal: true
module Interactors
class BaseInteractor
extend Dry::Initializer
include Dry::Transaction
include Dry::Logic
include Dry::Monads[:result]
end
end
# frozen_string_literal: true
require "base64"
module Interactors
module Base64
class EncodeInteractor < BaseInteractor
param :data, default: proc { "" }
step :contract
step :encode
private
def contract(input)
Contracts::Base64::EncodeContract.new.call(input).to_monad
end
def encode(input)
Success(cypher: ::Base64.encode64(input[:data]))
end
end
end
end
It's simples chain of interaction, but current layout is well covers my requirements for interactor of 10 steps with some branch actions. Next also I'll add layer of dry-matchers to convert dry-monades messages to formatted JSON API responses.
Describe the bug
I using Interactor based on
Validation::Contract
with mixed indry-initializer
anddry-transaction
. I trying to use schema for validation in one line with initializer to set default param values and convert types/formats for some of them usingdry-initializer
.To Reproduce
Loaded app components using Zeitwerk, didn't use dry-container in current case.
Spec failure:
Spec:
Contract class:
Schema:
Expected behavior
{data: nil}
,{data: ""}
.extend Dry::Initializer
.My environment