How to deal validation with list of entities to insert


I’m trying to insert a list of entities my using Enum.each but I have problem with how to deal with it if some validation fails.

I have external parameters from frontend:

[%{"option_id" => 2, "poll_id" => 1}, %{"option_id" => 3, "poll_id" => 1}]

Then in my context

    Enum.each(attrs, fn params ->
        |> Vote.changeset(params)
        |> Repo.insert()

When I look at the docs, Enum.each returns an :ok atom but what I want is to match the return with my controller.

  def cast_vote(conn, %{"vote" => vote_params}) do
    with  {:ok, _vote} <- Polls.cast_vote(vote_params) do
      send_resp(conn, :no_content, "")

I also want to return a 400 bad request when a validation error occurs in one of the elements of the list.

Put validation logic in your Vote.changeset/2. Study thoroughly.

As to the return of 400s, try using the fallback controllers feature in Phoenix this will be cleaner than pattern matching all the time

First step: Enum.each is only useful when you don’t care about the results - switching to will get you a list of {:ok, %Vote{}} | {:error, changeset} tuples.

From that, you can parse out if there were any errors.

Also consider what you want to happen to Vote records that are successfully inserted in the same request with a Vote that gets an error; should they be rolled back? Consider using a Repo.transaction block or an Ecto.Multi to coordinate saving multiple rows.