Skip to content

Commit

Permalink
feat: Add :one_of constraint to the Atom type (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
doawoo committed Oct 13, 2020
1 parent 57c0c72 commit 78861b6
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
28 changes: 28 additions & 0 deletions lib/ash/type/atom.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
defmodule Ash.Type.Atom do
@constraints [
one_of: [
type: :any,
doc: "Allows constraining the value of an atom to a pre-defined list"
]
]
@moduledoc """
Stores an atom as a string in the database
Expand All @@ -9,6 +15,28 @@ defmodule Ash.Type.Atom do
@impl true
def storage_type, do: :string

@impl true
def constraints, do: @constraints

def apply_constraints(nil, _), do: :ok

def apply_constraints(value, constraints) do
errors =
Enum.reduce(constraints, [], fn
{:one_of, atom_list}, errors ->
if Enum.member?(atom_list, value) do
errors
else
["atom must be one of `#{inspect(atom_list)}`" | errors]
end
end)

case errors do
[] -> :ok
errors -> {:error, errors}
end
end

@impl true
def cast_input(value) when is_atom(value) do
{:ok, value}
Expand Down
15 changes: 12 additions & 3 deletions test/type/type_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ defmodule Ash.Test.Type.TypeTest do
attributes do
attribute :id, :uuid, primary_key?: true, default: &Ecto.UUID.generate/0
attribute :title, PostTitle, constraints: [max_length: 10]
attribute :post_type, :atom, allow_nil?: false, constraints: [one_of: [:text, :video]]
end

actions do
Expand All @@ -75,16 +76,24 @@ defmodule Ash.Test.Type.TypeTest do
test "it accepts valid data" do
post =
Post
|> new(%{title: "foobar"})
|> new(%{title: "foobar", post_type: :text})
|> Api.create!()

assert post.title == "foobar"
end

test "it rejects invalid data" do
test "it rejects invalid title data" do
assert_raise(Ash.Error.Invalid, ~r/is too long, max_length is 10/, fn ->
Post
|> new(%{title: "foobarbazbuzbiz"})
|> new(%{title: "foobarbazbuzbiz", post_type: :text})
|> Api.create!()
end)
end

test "it rejects invalid atom data" do
assert_raise(Ash.Error.Invalid, ~r/atom must be one of/, fn ->
Post
|> new(%{title: "foobar", post_type: :something_else})
|> Api.create!()
end)
end
Expand Down

0 comments on commit 78861b6

Please sign in to comment.