Current section

Files

Jump to
leaf_through lib leaf_through.ex
Raw

lib/leaf_through.ex

defmodule LeafThrough do
@moduledoc """
Provides Ecto pagination functions.
"""
import Ecto.Query, only: [limit: 2, offset: 2, exclude: 2, select: 2]
import LeafThrough.Calculate
defmacro __using__(_options) do
quote do
@doc """
Paginates an Ecto query and returns a `Map` of the results for the given page number.
The map consists of the following metadata:
* entries: query results for the given page
* total_count: count of query results for all pages
* page: requested page
* pages: total pages
## Example map
%{ entries: [...], total_count: 14, page: 2, pages: 3 }
"""
@spec paginate(query :: Ecto.Query.t, integer) :: map
def paginate(query, page) do
LeafThrough.paginate(__MODULE__, query, page)
end
end
end
def paginate(repo, query, page_number) do
entries = entries(repo, query, page_number)
total_count = total_count(repo, query) || 0
pages = pages(total_count)
%{
entries: entries,
total_count: total_count,
page: page_number,
pages: pages
}
end
defp entries(repo, query, page_number) do
query
|> set_limit()
|> set_start(page_number)
|> retrieve(repo)
end
defp total_count(repo, query) do
query
|> reset_query()
|> count(repo)
end
defp set_limit(query) do
limit(query, ^per_page())
end
defp set_start(query, page_number) do
offset(query, ^starting_row(page_number))
end
defp retrieve(query, repo) do
repo.all(query)
end
defp reset_query(query) do
query
|> exclude(:select)
|> exclude(:preload)
|> exclude(:order_by)
end
defp count(query, repo) do
query
|> select(count("*"))
|> repo.one()
end
end