Skip to content

Commit 60dc935

Browse files
authored
improvement: TypedStruct required field pattern matching (#2265)
- Adds generated function head for `new!/1` for required fields closes #2253
1 parent 5d94561 commit 60dc935

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

lib/ash/typed_struct.ex

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ defmodule Ash.TypedStruct do
149149
end
150150
end)
151151

152+
map_required_fields_match =
153+
enforce_keys
154+
|> Enum.reject(&(&1 in Map.keys(defaults)))
155+
|> Enum.map(&{&1, {:_, [], Elixir}})
156+
|> then(&{:%{}, [], &1})
157+
152158
map_constraints =
153159
[
154160
fields:
@@ -181,11 +187,15 @@ defmodule Ash.TypedStruct do
181187
constraints: unquote(Macro.escape(map_constraints))
182188

183189
@doc "Create a new #{__MODULE__}, raising any error"
190+
def new!(unquote(map_required_fields_match) = fields) do
191+
fields
192+
|> new()
193+
|> Ash.Helpers.unwrap_or_raise!()
194+
end
195+
184196
def new!(fields) do
185-
case new(fields) do
186-
{:ok, value} -> value
187-
{:error, error} -> raise Ash.Error.to_error_class(error)
188-
end
197+
{:error, error} = new(fields)
198+
raise Ash.Error.to_error_class(error)
189199
end
190200

191201
@doc "Create a new #{__MODULE__}, or return an error"

test/typed_struct_test.exs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,31 @@ defmodule Ash.TypedStructTest do
101101
assert struct.active == false
102102
end
103103

104+
test "new! returns struct when all required fields are present" do
105+
assert %Ash.TypedStructTest.UserStruct{
106+
id: "123e4567-e89b-12d3-a456-426614174000",
107+
name: "John Doe",
108+
email: "john@example.com",
109+
age: 30
110+
} =
111+
UserStruct.new!(%{
112+
id: "123e4567-e89b-12d3-a456-426614174000",
113+
name: "John Doe",
114+
email: "john@example.com",
115+
age: 30
116+
})
117+
end
118+
119+
test "new! raises when required fields with no default are missing" do
120+
assert_raise Ash.Error.Invalid, fn ->
121+
UserStruct.new!(%{
122+
id: "123e4567-e89b-12d3-a456-426614174000",
123+
email: "invalid-email",
124+
age: 30
125+
})
126+
end
127+
end
128+
104129
test "new! raises on errors" do
105130
assert_raise Ash.Error.Invalid, fn ->
106131
UserStruct.new!(%{

0 commit comments

Comments
 (0)