I’ve created a new phoenix project with the --binary-id and --live options. I used a liveview generator to create a Restaurant schema and a MenuItem schema where MenuItem references the restaurant_id. I’m getting this error when doing a test insert of a menu_item that references a restaurant_id and getting this error:
value "5" for (restaurant_id) in insert does not match type :binary_id
This error is displayed in iex when manually doing an insert, and this is expected since 5 is not a UUID, not is it correctly referencing any id in restaurants. But in the UI since the process crashed I don’t see an error in the form. In practice this particular error should never happen since I don’t plan on allowing my users to directly type in the restaurant UUID, but I’m just thinking in general shouldn’t there be a way to surface the error into the changeset?
Is the only way to do a rescue around the Repo.insert and manually put the error into the changeset?
This kind of errors can be caught before touching Postgres using Ecto.UUID
type.
Here is example:
> types = %{id: Ecto.UUID}
%{id: Ecto.UUID}
> {%{}, types} |> Ecto.Changeset.cast(%{id: "5"}, [:id])
#Ecto.Changeset<
action: nil,
changes: %{},
errors: [id: {"is invalid", [type: Ecto.UUID, validation: :cast]}],
data: %{},
valid?: false
>
> {%{}, types} |> Ecto.Changeset.cast(%{id: UUID.uuid4}, [:id])
#Ecto.Changeset<
action: nil,
changes: %{id: "71973364-3444-4b35-9594-b668a331397e"},
errors: [],
data: %{},
valid?: true
>
1 Like
That was helpful thanks. I guess I didn’t know what the difference between binary_id and Ecto.UUID was. I thought the generators would already setup everything for me geared toward UUID since I initialized the app with the --binary-id flag. But I suppose binary_id is just a string and it doesn’t know how to validate itself as a proper UUID which is a particular kind of binary_id, of which binary_id is agnostic about since there could be many other kinds of binary_id.
So all I had to do was replace binary_id in my schemas with Ecto.UUID. Afterwards I still got a raised error when the foreign key constraint was violated, but the error was very clear on how to bring the error into the changeset. I just needed to add foreign_key_constraint/3 and now it works as expected.