Hi dry-rb community! Forgive me if I’m asking a repeat question, but I’ve searched issues and forums and tried quite a bit of experimentation, but I’m still not able to solve my issue.
I’m using dry-schema / dry-validation in Hanami, but this question felt more applicable to dry-rb since it’s mostly not about the Hanami framework.
Here’s the summary:
- I have a schema, nested under a top-level key.
- I want to break the schema up into components (e.g.
Name
,MailingAddress
, so I can use those components separately) - Then, I want to be able to compose those components back into this schema, nested under the top-level key
I can see how to compose schemas, and I can see how to nest — but I can’t figure out how to do both, and nothing I’ve tried has worked.
Here’s what I’d like to be able to do, where each of the classes is its own contract, with params, rules, and macros.
I think the first question is: is what I’m trying to do possible?
Thanks in advance for the help!
module MySlice
module Contracts
module AddressChangeRequest
class Create < MySlice::Contract
params do
required(:change_request).hash(
Name &
Email &
SocialSecurityNumber &
MailingAddress
)
end
end
end
end
end
Here’s the current state, which I’d like to break into components for the commented sections:
module Address
module Contracts
module ChangeRequest
class Create < Address::Contract
params do
required(:change_request).hash do
# Name
required(:first_name).filled(:string)
required(:last_name).filled(:string)
# Email
required(:email_address).filled(:string)
# Social security number
required(:social_security_number).filled(:string)
# Mailing address
required(:address_line_1).filled(:string)
required(:address_line_2).maybe(:string)
required(:city).filled(:string)
required(:state).filled(:string)
required(:zip).filled(:string)
end
end
# Would be part of the SocialSecurityNumber contract
# Rules for validating social security number characteristics
rule(change_request: :social_security_number).validate(:ssn_format)
rule(change_request: :social_security_number).validate(:ssn_zero_groups)
rule(change_request: :social_security_number).validate(:ssn_area_range)
# Would be part of the SocialSecurityNumber contract
# Definition of rules for validating social security number characteristics
register_macro(:ssn_format) do
# omitted for brevity
end
register_macro(:ssn_zero_groups) do
# omitted for brevity
end
register_macro(:ssn_area_range) do
# omitted for brevity
end
end
end
end
end
Valid params for both of these should be structured like:
{
change_request: {
first_name: "Matt",
last_name: "Cloyd",
# ... and so on ...
}
}