Search code examples
elixirecto

Best way to do something if map has keys in Elixir?


So I'm trying to implement a query function for a Collection table. And that table HAS to be filtered by :id, but it CAN be also filtered by :rating and :accessibility.

Right now I have a function that is something like this:

def find_collection(args) do...

Where args can be one of: %{id: id}, %{id: id, rating: rating}, %{id: id, accessibility: accessibility} or %{id: id, rating: rating, accessibility: accessibility}. And I need to make these in to ecto queries: [id: id], [id: id, rating: rating], etc...

I know I can make 4 different functions that expect different args, but that seems very non-reusable. Maybe someone could give me a hit a better way to do composable "if map has key a do this and key b do this"?


Solution

  • You might simply pass the argument as is to Ecto.Query.where/3. The safest way would be somewhat like:

    def find_collection(%{id: _} = args) do
      where_clause =
        args
        |> Map.take(~w|id rating accessibility|a)
        |> Map.to_list()
      from(t in Table, where: ^where_clause)
    end