Skip to content

Commit c003039

Browse files
committed
Add note and error about field type in validate_subset/3,4
Now raises an argument error if field type is not array. Previously, it would raise a match error, providing a worse DX.
1 parent cba84cc commit c003039

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

lib/ecto/changeset.ex

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,8 @@ defmodule Ecto.Changeset do
20232023
If you need to validate if a single value is inside the given enumerable,
20242024
you should use `validate_inclusion/4` instead.
20252025
2026+
Type of the field must be array.
2027+
20262028
## Options
20272029
20282030
* `:message` - the message on failure, defaults to "has an invalid entry"
@@ -2036,7 +2038,15 @@ defmodule Ecto.Changeset do
20362038
@spec validate_subset(t, atom, Enum.t, Keyword.t) :: t
20372039
def validate_subset(changeset, field, data, opts \\ []) do
20382040
validate_change changeset, field, {:subset, data}, fn _, value ->
2039-
{:array, element_type} = Map.fetch!(changeset.types, field)
2041+
element_type =
2042+
case Map.fetch!(changeset.types, field) do
2043+
{:array, element_type} ->
2044+
element_type
2045+
2046+
type ->
2047+
raise ArgumentError,
2048+
"validate_subset/4 expects field type to be array, field `#{inspect(field)}` has type `#{inspect(type)}`"
2049+
end
20402050

20412051
case Enum.any?(value, fn element -> not Ecto.Type.include?(element_type, element, data) end) do
20422052
true -> [{field, {message(opts, "has an invalid entry"), [validation: :subset, enum: data]}}]

test/ecto/changeset_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,13 @@ defmodule Ecto.ChangesetTest do
10901090
assert changeset.valid?
10911091
end
10921092

1093+
test "validate_subset/3 raises if field type is not array" do
1094+
assert_raise ArgumentError, "validate_subset/4 expects field type to be array, field `:title` has type `:string`", fn ->
1095+
changeset(%{"title" => "hello"})
1096+
|> validate_subset(:title, ["hello"])
1097+
end
1098+
end
1099+
10931100
test "validate_exclusion/3" do
10941101
changeset =
10951102
changeset(%{"title" => "world"})

0 commit comments

Comments
 (0)