defmodule EctoShorts.QueryBuilder.Common do
@moduledoc """
This module contains query building parts for common things such
as preload, start/end date and others
"""
import Logger, only: [debug: 1]
import Ecto.Query, only: [
offset: 2, preload: 2, where: 3, limit: 2,
exclude: 2, from: 2, subquery: 1, order_by: 2
]
alias EctoShorts.QueryBuilder
@behaviour QueryBuilder
@filters [
:preload,
:start_date,
:end_date,
:before,
:after,
:ids,
:first,
:last,
:limit,
:offset,
:search,
:order_by
]
@spec filters :: list(atom)
def filters, do: @filters
@impl QueryBuilder
def create_schema_filter({:preload, val}, query), do: preload(query, ^val)
@impl QueryBuilder
def create_schema_filter({:start_date, val}, query), do: where(query, [m], m.inserted_at >= ^(val))
@impl QueryBuilder
def create_schema_filter({:end_date, val}, query), do: where(query, [m], m.inserted_at <= ^val)
@impl QueryBuilder
def create_schema_filter({:before, id}, query), do: where(query, [m], m.id < ^id)
@impl QueryBuilder
def create_schema_filter({:after, id}, query), do: where(query, [m], m.id > ^id)
@impl QueryBuilder
def create_schema_filter({:ids, ids}, query), do: where(query, [m], m.id in ^ids)
@impl QueryBuilder
def create_schema_filter({:offset, val}, query), do: offset(query, ^val)
@impl QueryBuilder
def create_schema_filter({:limit, val}, query), do: limit(query, ^val)
@impl QueryBuilder
def create_schema_filter({:first, val}, query), do: limit(query, ^val)
@impl QueryBuilder
def create_schema_filter({:order_by, val}, query), do: order_by(query, ^val)
@impl QueryBuilder
def create_schema_filter({:last, val}, query) do
query
|> exclude(:order_by)
|> from(order_by: [desc: :inserted_at], limit: ^val)
|> subquery
|> order_by(:id)
end
@impl QueryBuilder
def create_schema_filter({:search, val}, query) do
schema = QueryBuilder.query_schema(query)
if function_exported?(schema, :by_search, 2) do
schema.by_search(query, val)
else
debug "create_schema_filter: #{inspect schema} doesn't define &search_by/2 (query, params)"
query
end
end
end