-
Notifications
You must be signed in to change notification settings - Fork 29
Description
Thank you so much for this library!
I'm not sure if I just missed this, or if it's a bad idea, or if there's a better way to achieve it - but does Norm include an "and" for specs/schemas, corresponding to the "or" provided by one_of?
For example, say I have two schemas like:
quick_checks = schema(%{
id: spec(is_integer()),
name: spec(is_string())
})
expensive_checks = schema(%{
id: spec(some_complex_calculation()),
age: spec(another_complex_calculation())
})Perhaps most of the time I only want to do the quick_checks, but on some occasions I want to do ALL the checks. Is there (/should there be) a way to compose the two schemas so that I end up with something like the following?
all_checks = schema(%{
id: spec(is_integer() and some_complex_calculation()),
name: spec(is_string()),
age: spec(another_complex_calculation())
})I guess if you're using conform!/2 it doesn't really matter, because you can just do
data
|> conform!(quick_checks)
|> conform!(expensive_checks)and you'll get an exception if something goes wrong.
But with conform/2 it's a bit trickier if you want to catch all the validation errors in one output. I wrote a helper function called conform_all, but it doesn't seem like a very elegant approach.
def conform_all(input, specs_and_schemas) do
Enum.reduce(specs_and_schemas, {:ok, input}, fn spec_or_schema, previous_result ->
case previous_result do
{:ok, input} ->
case conform(input, spec_or_schema) do
{:ok, input} -> {:ok, input}
{:error, new_errors} -> {:error, new_errors}
end
{:error, existing_errors} ->
case conform(input, spec_or_schema) do
{:ok, _input} -> {:error, existing_errors}
{:error, new_errors} -> {:error, existing_errors ++ new_errors}
end
end
end)
endApologies if I'm missed something obvious, and thanks so much again for Norm!