Skip to content

Instantly share code, notes, and snippets.

@brianberlin
Last active April 11, 2019 14:32
Show Gist options
  • Save brianberlin/112ba5589f3dc30e91e6174d5c098ca9 to your computer and use it in GitHub Desktop.
Save brianberlin/112ba5589f3dc30e91e6174d5c098ca9 to your computer and use it in GitHub Desktop.
Ecto Filter
defmodule Filters do
import Ecto.{Query}, warn: false
defmacro __using__(_opts) do
quote do
defp apply_filters(original_query, params) do
filters = create_filters(params)
query =
try do
Enum.reduce(filters, original_query, &filter/2)
rescue
_ -> original_query
end
maybe_apply_defaults(query, original_query, filters)
end
defp maybe_apply_defaults(query, original_query, filters) when query == original_query,
do: Enum.reduce(filters, query, &defaults/2)
defp maybe_apply_defaults(query, _, _), do: query
defp condition_bools(filters) do
Enum.map(filters, fn
{key, "true"} -> {key, true}
{key, "false"} -> {key, false}
{key, value} -> {key, value}
end)
end
defp filter_parameters(filters) do
Enum.filter(filters, fn
{_, nil} -> false
{_, ""} -> false
{key, value} -> true
_ -> false
end)
end
defp convert_string_keys(filters) do
Enum.map(filters, fn
{key, value} when is_binary(key) -> {String.to_existing_atom(key), value}
{key, value} -> {key, value}
end)
end
defp create_filters(%{"q" => parameters}) do
parameters
|> filter_parameters()
|> condition_bools()
|> convert_string_keys()
end
defp create_filters(_), do: []
defp defaults({key, value}, query) do
from(
[c] in query,
where: field(c, ^key) == ^value
)
end
defp defaults(_, query), do: query
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment