Filtering by enum attribute

psychonaugty
2023-08-21

psychonaugty:

I have an Ash resource that has an enum field status . Im using AshJsonApi to pass in a filter: filter[status]=active,incomplete . This doesnt seem to work out of the box so I implemented a preperation where I do this:

  defp filter_by_status(query) do
    case Ash.Changeset.get_argument(query, :filter) do
      %{"status" => statuses} ->
        all_statuses = String.split(statuses, ",")
        Ash.Query.filter(query, status in ^all_statuses)

      _ ->
        query
    end
  end

This does not work however, returns the following error:

[error] FrameworkError: Framework Error | something went wrong. Error messaging is incomplete so far: %Ash.Error.Query.InvalidFilterValue{message: nil, value: "active,incomplete", context: #Ecto.Query<from m0 in MembershipService.Memberships.Membership, as: 0, where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) ==
  type(
    ^"active,incomplete",
    {:parameterized, Ash.Type.Atom.EctoType,
     one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
  ), where: type(as(0).status, {:parameterized, Ash.Type.Atom.EctoType, []}) in [
  type(
    ^"active",
    {:parameterized, Ash.Type.Atom.EctoType,
     one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
  ),
  type(
    ^"incomplete",
    {:parameterized, Ash.Type.Atom.EctoType,
     one_of: [:active, :canceled, :incomplete, :incomplete_expired, :trialing, :past_due, :unpaid]}
  )
], 

Is there an example or an way to filter by an enum?

psychonaugty:

Inspecting the filter after adding my customer status filter, it looks like there is an original filter to find status but the direct string sent from the api through AshJsonApi:

  filter: #Ash.Filter<status == "active,incomplete" and status in [:active,
   :incomplete]>,

zachdaniel:

filter[status][in][0]=active&filter[status][in][1]=incomplete should do it

psychonaugty:

Do I have to write a custom filter expression for this or can it be handled automatically?

psychonaugty:

Getting an error when running with the array filter:

rror: "filter: Could not cast expression: Ash.Query.Operator.In status %{\"0\" => \"active\", \"1\" => \"incomplete\"}",

psychonaugty:

Whats also odd is that in the example repos for ash, the case on get_argument for filter has atom keys, but mine has string keys 🧐

zachdaniel:

that should be fine…

zachdaniel:

I think this may be something we’re missing in ash_json_api , we should be handling list query params like that properly and creating lists

zachdaniel:

can you open a bug in ash_json_api ?

zachdaniel:

I can fix it when I get the chance

psychonaugty:

Added!

psychonaugty:

In case anyone else runs into this, to filter by multiple values in an enum attribute, you need to filters your query params like so filter[status][in]=a&filter[status][in]=b where a & b are possible enum values