We have a few transactions that all take a “message” as input, along with a few other arguments that differ. In dry-validations < 1.0, we did something like this:
MessageSchema = Dry::Validation.Params do optional(:body).maybe(:str?) optional(:attachments).each do schema do required(:key).filled(:str?) required(:size).filled(:int?) required(:content_type).filled(:str?) optional(:width).maybe(:int?) optional(:height).maybe(:int?) end end optional(:saved_reply).maybe optional(:flags).maybe(:array?) optional(:scheduled_at).maybe(:time?, :in_the_future?) validate(has_content: [:body, :attachments]) do |body, attachments| body.present? || attachments.present? end end # Then in each transaction, we have a validation like this, each with different `required` params: Dry::Validation.Schema do required(:conversation).filled required(:user).filled required(:message).schema(MessageSchema) end
I’m trying to upgrade to dry-schema and dry-validations, and I’m having trouble accomplishing this. I can change it to
required(:message).hash(MessageSchema), but I have to change
MessageSchema to a dry-schema, and there’s no way to accomplish the
body.present? || attachments.present? checks. If I convert
MessageSchema to a
Contract, I can’t pass it to
required(:message).hash(MessageContract), it fails with
undefined methodto_ast’ for #MessageContract:0x000055d600d0fc38`.
Is it possible to compose validations like this? I could write a
:valid_message? macro that does
MessageContract.new.call(value), but that would lose the validation error messages on message, wouldn’t it?