Current section

10 Versions

Jump to

Compare versions

6 files changed
+48 additions
-7 deletions
  @@ -24,6 +24,8 @@ defmodule User do
24 24 attribute(:name, Types.String)
25 25 attribute(:age, Types.Integer.options(optional: true))
26 26 attribute(:height)
27 + attribute(:brother, Sibling.options(optional: true))
28 + attribute(:sister, Sibling.options(default: %Sibling{name: "Karen"}))
27 29 attribute(:country, Types.String.options(default: "UK"))
28 30 attribute(:siblings, Types.Array.options(type: Sibling))
29 31 attribute(:favourite_colours, Types.Array.options(type: Types.String, default: ["blue", "green"]))
  @@ -45,6 +47,8 @@ user == %User{
45 47 height: 169,
46 48 is_adult: true,
47 49 name: "Rob",
50 + brother: nil,
51 + sister: %Sibling{name: "Karen"},
48 52 tall: false,
49 53 siblings: [%Sibling{name: "John"}],
50 54 favourite_colours: ["blue", "green"]
  @@ -60,7 +64,7 @@ by adding `dry` to your list of dependencies in `mix.exs`:
60 64 ```elixir
61 65 def deps do
62 66 [
63 - {:dry, 0.1.1"}
67 + {:dry, 0.1.2"}
64 68 ]
65 69 end
66 70 ```
  @@ -4,12 +4,12 @@
4 4 {<<"elixir">>,<<"~> 1.11">>}.
5 5 {<<"files">>,
6 6 [<<"lib">>,<<"lib/dry.ex">>,<<"lib/types">>,<<"lib/types/float.ex">>,
7 - <<"lib/types/bool.ex">>,<<"lib/types/string.ex">>,<<"lib/types/atom.ex">>,
8 - <<"lib/types/array.ex">>,<<"lib/types/map.ex">>,<<"lib/types/integer.ex">>,
9 - <<"lib/runtime_error.ex">>,<<"lib/processor.ex">>,<<".formatter.exs">>,
10 - <<"mix.exs">>,<<"README.md">>]}.
7 + <<"lib/types/struct.ex">>,<<"lib/types/bool.ex">>,<<"lib/types/string.ex">>,
8 + <<"lib/types/atom.ex">>,<<"lib/types/array.ex">>,<<"lib/types/map.ex">>,
9 + <<"lib/types/integer.ex">>,<<"lib/runtime_error.ex">>,
10 + <<"lib/processor.ex">>,<<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>]}.
11 11 {<<"licenses">>,[<<"Apache-2.0">>]}.
12 12 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/gmartsenkov/dry_ex">>}]}.
13 13 {<<"name">>,<<"dry">>}.
14 14 {<<"requirements">>,[]}.
15 - {<<"version">>,<<"0.1.1">>}.
15 + {<<"version">>,<<"0.1.2">>}.
  @@ -56,6 +56,7 @@ defmodule Dry do
56 56 end
57 57 end
58 58
59 + # credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
59 60 defmacro schema(do: block) do
60 61 prelude =
61 62 quote do
  @@ -105,6 +106,12 @@ defmodule Dry do
105 106 def valid?(%{__struct__: __MODULE__} = value) when is_struct(value), do: true
106 107 def valid?(_value), do: false
107 108
109 + def options(opts \\ []) do
110 + opts
111 + |> Keyword.put(:type, __MODULE__)
112 + |> Dry.Types.Struct.options()
113 + end
114 +
108 115 @doc "Used to recognise Dry modules"
109 116 def __dry__(), do: true
110 117 end
  @@ -26,6 +26,13 @@ defmodule Dry.Processor do
26 26 message: "[#{inspect(module)}] - Required attribute :#{name} is missing"
27 27 end
28 28
29 + def process(name, %Types.Struct{type: type}, value, module) do
30 + Code.ensure_loaded(type)
31 + functions = type.__info__(:functions) |> Enum.into(%{})
32 +
33 + process_advanced(name, type, functions, value, module)
34 + end
35 +
29 36 def process(name, %Types.Array{type: type}, value, module) do
30 37 converted = convert_list(name, type, value, module)
  @@ -0,0 +1,23 @@
1 + defmodule Dry.Types.Struct do
2 + @moduledoc """
3 + Represents the struct type
4 +
5 + ## Examples:
6 + ```elixir
7 + schema do
8 + ttribute :field_1, Types.Struct
9 + attribute :field_2, Types.Struct.options(optional: true)
10 + attribute :field_2, Types.Struct.options(default: %Struct{a: 1})
11 + end
12 + """
13 +
14 + defstruct [:type, :default, :optional]
15 +
16 + @doc "Valid options are :type, :default and :optional"
17 + def options(opts \\ []) do
18 + struct(__MODULE__, opts)
19 + end
20 +
21 + def valid?(value) when is_struct(value), do: true
22 + def valid?(_value), do: false
23 + end
Loading more files…