Default sorting for BoxTurtle.Schema.Query, and a base for schema-specific sort modules.
A sort specification is a list whose elements are any of:
:column- ascending order on the column{direction, :column}- e.g.{:desc_nulls_last, :reported_at}{direction, [:column, ...]}- the same direction for several columns
where direction is one of [:asc, :asc_nulls_first, :asc_nulls_last, :desc, :desc_nulls_first, :desc_nulls_last]
(see Ecto.Query.order_by/3). Keyword lists such as [desc: :inserted_at, asc: :id] therefore work as-is.
Custom sorts
Use this module and add sort_by/2 clauses for named sorts that aren't plain columns. Each clause
handles the element at the head of the list and must pass the rest back to sort_by/2. Elements
your clauses don't match fall through to the default behaviour, one element at a time.
For a MyApp.Blog.Post schema with likes and shares fields:
defmodule MyApp.Blog.Post.Sort do
use BoxTurtle.Schema.Sort
import Ecto.Query
# Most engagement first; the primary key breaks ties so pages are stable.
def sort_by(query, [:popularity | rest]) do
query
|> order_by([p], desc: p.likes + p.shares, asc: p.id)
|> sort_by(rest)
end
end
defmodule MyApp.Blog.Post.Query do
use BoxTurtle.Schema.Query,
repo: MyApp.Repo,
sorting_module: MyApp.Blog.Post.Sort,
default_sort: [:popularity]
end
MyApp.Blog.Post.Query.list!() # most popular first
MyApp.Blog.Post.Query.list!(sort: [desc: :inserted_at, asc: :id]) # plain columns still work:default_sort goes through your module too, so it may use your named sorts. Sorts on joined
columns and closed modules for ?sort=-likes,title params are shown in the repository's
test/support/examples/schema.ex.
Summary
Functions
Applies a single sort element (see the module documentation) to the query.
Functions
@spec apply_sort(Ecto.Queryable.t(), term()) :: Ecto.Queryable.t()
Applies a single sort element (see the module documentation) to the query.
Raises ArgumentError for anything else.