Packages

Elixir utils.

Retired package: Deprecated - Use instead antl_utils_* packages

Current section

Files

Jump to
antl_utils lib ecto queryable.ex
Raw

lib/ecto/queryable.ex

if Code.ensure_loaded?(Ecto) do
defmodule AntlUtils.Ecto.Queryable do
@callback queryable() :: Ecto.Queryable.t()
@callback paginate(Ecto.Queryable.t(), integer, keyword) :: Ecto.Queryable.t()
@callback sort(Ecto.Queryable.t(), map) :: Ecto.Queryable.t()
@callback filter(Ecto.Queryable.t(), map) :: Ecto.Queryable.t()
@callback search(Ecto.Queryable.t(), binary) :: Ecto.Queryable.t()
defmacro __using__(opts) do
quote do
@behaviour unquote(__MODULE__)
@before_compile unquote(__MODULE__)
import Ecto.Query
@sortable_fields Keyword.get(unquote(opts), :sortable_fields, [:inserted_at, :updated_at])
@searchable_fields Keyword.get(unquote(opts), :searchable_fields, [:id])
def queryable(), do: Keyword.get(unquote(opts), :base_schema, __MODULE__)
defoverridable queryable: 0
def paginate(queryable, page, opts \\ []),
do: unquote(__MODULE__).paginate(queryable, page, opts)
def sort(queryable, sort_params \\ %{})
def sort(queryable, %{field: field, order: _order} = sort_params) do
handle_sort(queryable, sort_params)
end
def sort(queryable, %{}) do
sort(queryable, %{field: List.first(@sortable_fields), order: :desc})
end
defp handle_sort(queryable, %{field: field, order: _order} = sort_params)
when field in @sortable_fields do
unquote(__MODULE__).sort(queryable, sort_params)
end
def filter(queryable, filters),
do: Enum.reduce(filters, queryable, &filter_by_field(&1, &2))
def search(queryable, search_query, metadata \\ [])
def search(queryable, nil, _metadata), do: queryable
def search(queryable, search_query, metadata)
when is_binary(search_query) and is_list(metadata),
do: where(queryable, ^search_where_query(search_query, metadata))
defp search_where_query(search_query, []) do
Enum.reduce(
@searchable_fields,
Ecto.Query.dynamic(false),
&search_by_field({&1, search_query}, &2)
)
end
defp search_where_query(search_query, metadata) when length(metadata) > 0 do
Enum.reduce(
@searchable_fields,
Ecto.Query.dynamic(false),
&search_by_field({&1, search_query}, &2, metadata)
)
end
end
end
defmacro __before_compile__(_env) do
quote do
defp filter_by_field(field, queryable),
do: unquote(__MODULE__).filter_by_field(field, queryable)
defp search_by_field(field, dynamic),
do: unquote(__MODULE__).search_by_field(field, dynamic)
defp search_by_field(field, dynamic, metadata),
do: unquote(__MODULE__).search_by_field(field, dynamic, metadata)
end
end
import Ecto.Query
@spec paginate(Ecto.Queryable.t(), number, keyword) :: Ecto.Queryable.t()
def paginate(queryable, page, opts \\ []) do
queryable |> AntlUtils.Ecto.Paginator.paginate(page, opts)
end
@spec sort(any, map) :: Ecto.Queryable.t()
def sort(queryable, %{field: field, order: order})
when is_atom(field) and order in [:asc, :desc] do
queryable |> AntlUtils.Ecto.Query.order_by(field, order)
end
@spec filter_by_field({any, any}, any) :: Ecto.Queryable.t()
def filter_by_field({key, value}, queryable) do
queryable |> AntlUtils.Ecto.Query.where(key, value)
end
@spec search_by_field({any, binary}, any) :: Ecto.Query.DynamicExpr.t()
def search_by_field({key, value}, dynamic) do
like_value = "%#{String.replace(value, "%", "\\%")}%"
dynamic([q], ^dynamic or like(field(q, ^key), ^like_value))
end
@spec search_by_field({any, binary}, any, list()) :: Ecto.Query.DynamicExpr.t()
def search_by_field({key, value}, dynamic, metadata) when is_list(metadata) do
like_value = "%#{String.replace(value, "%", "\\%")}%"
dynamic([q], ^dynamic or like(field(q, ^key), ^like_value))
end
end
end