Default filtering for BoxTurtle.Schema.Query, and a base for schema-specific filter modules.
Each filter is a {column, value} pair, combined with AND:
{:status, "active"}-status = 'active'{:status, ["active", "pending"]}-status IN (...){:deleted_at, nil}-deleted_at IS NULL
String column names are accepted, but only if the atom already exists (String.to_existing_atom/1), so
filters built from request params can't create atoms.
Custom filters
Use this module and add filter_with/2 clauses for named filters that aren't plain column comparisons.
Each clause matches the filter at the head of the list and must pass the rest back to filter_with/2.
Filters your clauses don't match fall through to the default behaviour, one filter at a time.
For a MyApp.Blog.Post schema with likes and published_at fields:
defmodule MyApp.Blog.Post.Filters do
use BoxTurtle.Schema.Filters
import Ecto.Query
def filter_with(query, [{:published_after, %DateTime{} = date} | rest]) do
query
|> where([p], p.published_at > ^date)
|> filter_with(rest)
end
def filter_with(query, [{:min_likes, likes} | rest]) do
query
|> where([p], p.likes >= ^likes)
|> filter_with(rest)
end
end
defmodule MyApp.Blog.Post.Query do
use BoxTurtle.Schema.Query, repo: MyApp.Repo, filter_module: MyApp.Blog.Post.Filters
end
# Custom and plain column filters mix freely, in any order.
last_week = DateTime.add(DateTime.utc_now(), -7, :day)
MyApp.Blog.Post.Query.list!(filters: [published_after: last_week, status: "published", min_likes: 10])Custom clauses see keys exactly as given, so match atoms and convert request params yourself.
For more patterns (joins, subqueries, and closed allow-list modules for request params), see the
reference modules in the repository's test/support/examples/schema.ex.
Summary
Functions
Applies a single {column, value} filter (see the module documentation) to the query.
Functions
@spec apply_filter(Ecto.Queryable.t(), {atom() | String.t(), term()}) :: Ecto.Queryable.t()
Applies a single {column, value} filter (see the module documentation) to the query.