ex_admin icon indicating copy to clipboard operation
ex_admin copied to clipboard

batch_action exception for uuid id's

Open manthesepeasrock opened this issue 7 years ago • 4 comments

I have all my models with uuid for id's instead of integers, when executing a batch_action destroy, ex_admin gives an exception, this is caused because it tries to convert the model id from string to int and given that they are uuid it fails.

def batch_action(conn, defn, %{batch_action: "destroy"} = params) do
    resource_model = defn.resource_model

    type = case ExAdmin.Schema.primary_key(resource_model) do
      nil -> :integer
      key -> resource_model.__schema__(:type, key)
    end

    ids = params[:collection_selection]
    count = Enum.count ids
    ids
    |> Enum.map(&(to_integer(type, &1)))
    |> Enum.each(fn(id) ->
      repo().delete repo().get(resource_model, id)
    end)

    put_flash(conn, :notice, "#{count} #{pluralize params[:resource], count} "
              <> (ngettext "was successfully destroyed.", "were successfully destroyed.", count))
    |> redirect(to: admin_resource_path(resource_model, :index))
  end

this is the line that causes the problem

    |> Enum.map(&(to_integer(type, &1)))

Deleting line by line works well, only when using the batch options does not

manthesepeasrock avatar Apr 18 '17 15:04 manthesepeasrock

adding this to admin_resource_controller.ex fixes the problem

defp to_integer(:binary_id, string), do: string

manthesepeasrock avatar Apr 18 '17 15:04 manthesepeasrock

I have the same issue. The test suite has a test called "batch selection for binary id" but it's not testing this case, only in case there's no id.

I'm preparing a pull request with the fix.

benrom avatar May 16 '17 12:05 benrom

I'm reopening to pick up the test.

smpallen99 avatar May 16 '17 15:05 smpallen99

Even with those changes, if the primary key is defined like {:id, Ecto.UUID, autogenerate: true}, those function headers won't match. Why not use a wildcard catch-all after the :integer function head?


  defp to_integer(:id, string), do: string
  defp to_integer(:string, string), do: string
  defp to_integer(:binary_id, string), do: string
  defp to_integer(:integer, string) do
    case Integer.parse string do
      {int, ""} -> int
      _ -> string
    end
  end

defp to_integer(_, string), do: string

arvidkahl avatar Sep 13 '17 12:09 arvidkahl