Skip to content

Commit 4b7d5a8

Browse files
committed
Support custom caster modules
1 parent 83a2097 commit 4b7d5a8

File tree

4 files changed

+29
-9
lines changed

4 files changed

+29
-9
lines changed

lib/drops/contract.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,16 @@ defmodule Drops.Contract do
7070
def step(
7171
data,
7272
{:validate,
73-
%{type: {:cast, {{input_type, input_predicates}, output_type}}} = key}
73+
%{type: {:cast, {{input_type, input_predicates, cast_opts}, output_type}}} =
74+
key}
7475
) do
7576
value = get_in(data, key.path)
77+
caster = cast_opts[:caster] || Casters
7678

7779
case apply_predicates(value, input_predicates, path: key.path) do
7880
{:ok, _} ->
7981
validate(
80-
Casters.cast(input_type, output_type, value),
82+
caster.cast(input_type, output_type, value),
8183
key.predicates,
8284
path: key.path
8385
)

lib/drops/contract/dsl.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ defmodule Drops.Contract.DSL do
77
{:optional, name}
88
end
99

10-
def from(type) do
11-
{:cast, type}
10+
def from(type, cast_opts \\ []) do
11+
{:cast, {type, cast_opts}}
1212
end
1313

1414
def type([list: members]) when is_map(members) do
@@ -35,7 +35,7 @@ defmodule Drops.Contract.DSL do
3535
{:type, {type, predicates}}
3636
end
3737

38-
def type({:cast, input_type}, output_type) do
39-
{:cast, {type(input_type), type(output_type)}}
38+
def type({:cast, {input_type, cast_opts}}, output_type) do
39+
{:cast, {type(input_type), type(output_type), cast_opts}}
4040
end
4141
end

lib/drops/contract/schema/key.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ defmodule Drops.Contract.Schema.Key do
3838
Enum.map(spec, &infer_type(&1, opts))
3939
end
4040

41-
defp infer_type({:cast, {input_type, output_type}}, opts) do
41+
defp infer_type({:cast, {input_type, output_type, cast_opts}}, opts) do
4242
{:cast,
43-
{{infer_type(input_type, opts), infer_predicates(input_type, opts)},
43+
{{infer_type(input_type, opts), infer_predicates(input_type, opts), cast_opts},
4444
infer_type(output_type, opts)}}
4545
end
4646

47-
defp infer_predicates({:cast, {_input_type, output_type}}, opts) do
47+
defp infer_predicates({:cast, {_input_type, output_type, _cast_opts}}, opts) do
4848
infer_predicates(output_type, opts)
4949
end
5050

test/contract/casters_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,22 @@ defmodule Drops.CastersTest do
3636
assert {:ok, %{test: 31.2}} = contract.conform(%{test: "31.2"})
3737
end
3838
end
39+
40+
describe "using a customer caster" do
41+
contract do
42+
defmodule CustomCaster do
43+
def cast(:string, :string, value) do
44+
String.downcase(value)
45+
end
46+
end
47+
48+
schema do
49+
%{required(:test) => from(:string, caster: CustomCaster) |> type(:string)}
50+
end
51+
end
52+
53+
test "defining a required key with coercion", %{contract: contract} do
54+
assert {:ok, %{test: "hello"}} = contract.conform(%{test: "HELLO"})
55+
end
56+
end
3957
end

0 commit comments

Comments
 (0)