This isn’t specifically a question about the behaviour of dry-validation, but rather a question of whether dry-validation fits this use-case or whether something else is more appropriate.
Part of our company’s workflow allows a user to create records with relaxed validations in an inactive state. A more strict set of validations is then applied when the user attempts to activate the record.
For example, the creation flow might contain something like:
class CreateProductContract < ApplicationContract
params do
optional(:name).value(:string)
# ... omitted for brevity ...
end
end
Whereas the activation flow would have constraints such that:
class ActivateProductContract < ApplicationContract
params do
required(:name).filled(:string)
# ... omitted for brevity ...
end
end
The gotcha here is that the name
attribute isn’t part of the activation request. The frontend sends only an id
to an activation endpoint, and data is loaded from the record for the action.
To my understanding, to use dry-validation for this, the record and its associations would need to be decomposed into a Hash to be run through the contract. Basically, something that does:
def map_catalog_item_to_product(catalog_item)
{
name: catalog_item.title,
variants: map_offering_sizes_to_variants(catalog_item.offering.sizes),
# ... omitted for brevity ...
}
end
I’m hesitant to take this approach as the validated data structure is quite deep, and encapsulates quite a few nested data objects with a good 50 fields between them. This would be quite the time sink, both in terms of maintenance time and run time.
Currently we leverage Rails to perform model validations, where some validations are being run inside of an on: :activation
scope. Roughly:
class CatalogItem < ApplicationRecord # Referred to as `Product` in public API
# ...
validates :title, presence: true, on: :activation # Referred to as `name` in public API
# ...
end
This works but also creates another big problem, because the frontend relies on the error keys being consistent with the keys in the request payloads.
Errors produced by ActiveRecord match the data structure of our database rather than the data structure of our API, forcing us to perform a lot of flakey transformations and mapping. (ie. title
vs. name
above.)
TL;DR:
- Is dry-validation capable of / intended for validating data outside of a request?
- Is there a better library or better approach to this class of problem?
- If building out a Hash is a viable approach, is there a way to do it more cleanly? I’ve looked at
Transproc
, but that looks to be intended for transforming scalar types and doesn’t play well with ActiveRecord models.