Skip to content

Commit

Permalink
Refine rule behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
solnic committed Oct 20, 2023
1 parent dc52ea8 commit eaef511
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
17 changes: 14 additions & 3 deletions lib/drops/contract.ex
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,24 @@ defmodule Drops.Contract do
["email or login must be present"]
"""
defmacro rule(name, input, do: block) do
quote do
defmacro rule(name, {data, _line, rest} = input, do: block) when is_atom(data) do
pre = quote do
Module.put_attribute(__MODULE__, :rules, unquote(name))

def rule(unquote(name), unquote(input)), do: unquote(block)
end

def rule(unquote(name), _), do: :ok
post = if is_nil(rest) do
[]
else
quote do
def rule(unquote(name), _), do: :ok
end
end

quote do
unquote(pre)
unquote(post)
end
end

Expand Down
33 changes: 33 additions & 0 deletions test/contract/rule_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,37 @@ defmodule Drops.Contract.RuleTest do
)
end
end

describe "rule/1 with guard clauses" do
contract do
schema do
%{
optional(:login) => maybe(:string, [:filled?]),
optional(:email) => maybe(:string, [:filled?])
}
end

rule(:auth_required, data) do
if is_nil(data[:login]) and is_nil(data[:email]) do
{:error, "either login or email required"}
else
:ok
end
end
end

test "returns success when schema and rules passed", %{contract: contract} do
assert {:ok, %{login: "jane"}} = contract.conform(%{login: "jane", email: nil})

assert {:ok, %{email: "[email protected]"}} =
contract.conform(%{login: nil, email: "[email protected]"})
end

test "returns rule errors", %{contract: contract} do
assert_errors(
["either login or email required"],
contract.conform(%{login: nil, email: nil})
)
end
end
end

0 comments on commit eaef511

Please sign in to comment.