From eaef511aae9e4a745cee809feec0e4be9851ac98 Mon Sep 17 00:00:00 2001 From: Peter Solnica Date: Fri, 20 Oct 2023 10:59:12 +0200 Subject: [PATCH] Refine rule behavior --- lib/drops/contract.ex | 17 ++++++++++++++--- test/contract/rule_test.exs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/drops/contract.ex b/lib/drops/contract.ex index cbbf539..ae1178a 100644 --- a/lib/drops/contract.ex +++ b/lib/drops/contract.ex @@ -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 diff --git a/test/contract/rule_test.exs b/test/contract/rule_test.exs index 9b2918c..4ca652b 100644 --- a/test/contract/rule_test.exs +++ b/test/contract/rule_test.exs @@ -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: "jane@doe.org"}} = + contract.conform(%{login: nil, email: "jane@doe.org"}) + end + + test "returns rule errors", %{contract: contract} do + assert_errors( + ["either login or email required"], + contract.conform(%{login: nil, email: nil}) + ) + end + end end