Skip to content

Commit

Permalink
wip - port Sum
Browse files Browse the repository at this point in the history
  • Loading branch information
solnic committed Jan 18, 2024
1 parent 5ff7440 commit d430bef
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 10 deletions.
19 changes: 19 additions & 0 deletions lib/drops/contract.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ defmodule Drops.Contract do
end
end

def conform(data, %Types.Sum{} = type, path: path) do
case conform(data, type.left, path: path) do
{:ok, output} = success ->
success

{:error, left_error} ->
case conform(data, type.right, path: path) do
{:ok, output} = success ->
success

{:error, right_error} ->
{:error,
@message_backend.errors(
{:error, {path, {:or, {left_error, right_error}}}}
)}
end
end
end

defp apply_rules(output) do
Enum.map(rules(), fn name -> apply(__MODULE__, :rule, [name, output]) end)
|> Enum.filter(fn
Expand Down
4 changes: 4 additions & 0 deletions lib/drops/types/map/key.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ defmodule Drops.Types.Map.Key do
Map.has_key?(map, key) and present?(map[key], tail)
end

defp nest_result({:error, {:or, {left, right}}}, root) do
{:error, {:or, {nest_result(left, root), nest_result(right, root)}}}
end

defp nest_result({:error, {:list, results}}, root) when is_list(results) do
{:error, {root, {:list, Enum.with_index(results, &nest_result(&1, root ++ [&2]))}}}
end
Expand Down
4 changes: 2 additions & 2 deletions lib/drops/types/sum.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ defmodule Drops.Types.Sum do
{:ok, value} ->
{:ok, value}

{:error, left_error} ->
{:error, _} = left_error ->
case Drops.Type.Validator.validate(right, input) do
{:ok, value} ->
{:ok, value}

{:error, right_error} ->
{:error, _} = right_error ->
{:error, {:or, {left_error, right_error}}}
end
end
Expand Down
32 changes: 26 additions & 6 deletions lib/drops/validator/messages/backend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,40 @@ defmodule Drops.Validator.Messages.Backend do
end

defp error({:error, {path, {:map, errors}}}) do
Error.Conversions.nest(
nest(
%Error.Set{
errors: Enum.reject(Enum.map(errors, &error/1), &is_nil/1)
},
path
)
end

defp error({:error, {:map, results}}) when is_list(results) do
%Error.Set{
errors: Enum.reject(Enum.map(results, &error/1), &is_nil/1)
}
end

defp error({:error, {value, [predicate: predicate, args: _] = meta}}) do
%Error.Type{text: text(predicate, value), meta: meta}
end

defp error({:error, {path, {:list, results}}}) when is_list(results) do
errors = Enum.map(results, &error/1) |> Enum.reject(&is_nil/1)
if Enum.empty?(errors), do: nil, else: %Error.Set{errors: errors}
end

defp error({:error, {:list, results}}) when is_list(results) do
errors =
Enum.with_index(results, fn
{:error, _} = result, index -> nest(error(result), [index])
{:ok, _}, _ -> nil
end)
|> Enum.reject(&is_nil/1)

if Enum.empty?(errors), do: nil, else: %Error.Set{errors: errors}
end

defp error(results) when is_list(results) do
errors = Enum.map(results, &error/1) |> Enum.reject(&is_nil/1)
if Enum.empty?(errors), do: nil, else: %Error.Set{errors: errors}
Expand All @@ -123,11 +144,8 @@ defmodule Drops.Validator.Messages.Backend do
%Error.Rule{path: path, text: text}
end

defp error({:error, {path, {:or, {left, right}}}}) do
%Error.Sum{
left: error({:error, {path, left}}),
right: error({:error, {path, right}})
}
defp error({:error, {:or, {left, right}}}) do
%Error.Sum{left: error(left), right: error(right)}
end

defp error({:error, {path, {:cast, error}}}) do
Expand All @@ -136,6 +154,8 @@ defmodule Drops.Validator.Messages.Backend do

defp error(:ok), do: nil
defp error({:ok, _}), do: nil

defp nest(error, path), do: Error.Conversions.nest(error, path)
end
end
end
4 changes: 2 additions & 2 deletions test/contract/types/custom_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ defmodule Drops.Contract.Types.CustomTest do
end

test "returns errors with invalid input", %{contract: contract} do

Check failure on line 19 in test/contract/types/custom_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.15.7, 26.1)

test using a custom type returns errors with invalid input (Drops.Contract.Types.CustomTest)

Check failure on line 19 in test/contract/types/custom_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.15.7, 25.3)

test using a custom type returns errors with invalid input (Drops.Contract.Types.CustomTest)

Check failure on line 19 in test/contract/types/custom_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.14.5, 26.1)

test using a custom type returns errors with invalid input (Drops.Contract.Types.CustomTest)

Check failure on line 19 in test/contract/types/custom_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (1.14.5, 25.3)

test using a custom type returns errors with invalid input (Drops.Contract.Types.CustomTest)
assert_errors ["test must be a string"], contract.conform(%{test: 1})
assert_errors ["test must be filled"], contract.conform(%{test: ""})
assert_errors(["test must be a string"], contract.conform(%{test: 1}))
assert_errors(["test must be filled"], contract.conform(%{test: ""}))
end
end
end

0 comments on commit d430bef

Please sign in to comment.