Rummage.Ecto v2.0.0 Rummage.Ecto.Hook.Paginate View Source
Rummage.Ecto.Hook.Paginate is the default pagination hook that comes with
Rummage.Ecto.
This module provides a operations that can add pagination functionality to
a pipeline of Ecto queries. This module works by taking a per_page, which
it uses to add a limit to the query and by setting the offset using the
page variable, which signifies the current page of entries to be displayed.
NOTE: This module doesn't return a list of entries, but a Ecto.Query.t.
This module uses Rummage.Ecto.Hook.
ABOUT:
Arguments:
This Hook expects a queryable (an Ecto.Queryable) and
paginate_params (a Map). The map should be in the format:
%{per_page: 10, page: 1}
Details:
per_page: Specifies the entries in each page.page: Specifies thepagenumber.
For example, if we want to paginate products, we would do the following:
Rummage.Ecto.Hook.Paginate.run(Product, %{per_page: 10, page: 1})ASSUMPTIONS/NOTES:
NONE: This Hook should work for all the Schema types. Whether the schema has
a primary_key or not, this should handle that.
USAGE:
To add pagination to a Ecto.Queryable, simply do the following:
Rummage.Ecto.Hook.Paginate.run(queryable, %{per_page: 10, page: 2})Overriding:
This module can be overridden with a custom module while using Rummage.Ecto
in Ecto struct module.
In the Ecto module:
Rummage.Ecto.rummage(queryable, rummage, paginate: CustomHook)OR
Globally for all models in config.exs:
config :rummage_ecto,
Rummage.Ecto,
.paginate: CustomHookThe CustomHook must use Rummage.Ecto.Hook. For examples of CustomHook,
check out some custom_hooks that are shipped with Rummage.Ecto:
Rummage.Ecto.CustomHook.SimpleSearch, Rummage.Ecto.CustomHook.SimpleSort,
Rummage.Ecto.CustomHook.SimplePaginate
Link to this section Summary
Functions
Callback implementation for Rummage.Ecto.Hook.format_params/3.
This is the callback implementation of Rummage.Ecto.Hook.run/2.
Link to this section Functions
Specs
format_params(Ecto.Query.t(), map(), keyword()) :: map()
format_params(Ecto.Query.t(), map() | atom(), keyword()) :: map()
Callback implementation for Rummage.Ecto.Hook.format_params/3.
This function takes an Ecto.Query.t or queryable, paginate_params which
will be passed to the run/2 function, but also takes a list of options,
opts.
The function expects opts to include a repo key which points to the
Ecto.Repo which will be used to calculate the total_count and max_page
for this paginate hook module.
Examples
When a repo isn't passed in opts it gives an error:
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Category
iex> Paginate.format_params(Category, %{per_page: 1, page: 1}, [])
** (RuntimeError) Expected key `repo` in `opts`, got []When paginate_params given aren't valid, it uses defaults to populate params:
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Category
iex> Ecto.Adapters.SQL.Sandbox.checkout(Rummage.Ecto.Repo)
iex> Paginate.format_params(Category, %{}, [repo: Rummage.Ecto.Repo])
%{max_page: 0, page: 1, per_page: 10, total_count: 0}When paginate_params and opts given are valid:
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Category
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> Paginate.format_params(Category, paginate_params, [repo: repo])
%{max_page: 0, page: 1, per_page: 1, total_count: 0}When paginate_params and opts given are valid:
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Category
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> repo.insert!(%Category{name: "name"})
iex> repo.insert!(%Category{name: "name2"})
iex> Paginate.format_params(Category, paginate_params, [repo: repo])
%{max_page: 2, page: 1, per_page: 1, total_count: 2}When paginate_params and opts given are valid and when the queryable
passed has a primary_key defaulted to id.
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Category
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> repo.insert!(%Category{name: "name"})
iex> repo.insert!(%Category{name: "name2"})
iex> Paginate.format_params(Category, paginate_params, [repo: repo])
%{max_page: 2, page: 1, per_page: 1, total_count: 2}When paginate_params and opts given are valid and when the queryable
passed has a custom primary_key.
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Product
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> repo.insert!(%Product{internal_code: "100"})
iex> repo.insert!(%Product{internal_code: "101"})
iex> Paginate.format_params(Product, paginate_params, [repo: repo])
%{max_page: 2, page: 1, per_page: 1, total_count: 2}When paginate_params and opts given are valid and when the queryable
passed has a custom primary_key.
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Employee
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> repo.insert!(%Employee{first_name: "First"})
iex> repo.insert!(%Employee{first_name: "Second"})
iex> Paginate.format_params(Employee, paginate_params, [repo: repo])
%{max_page: 2, page: 1, per_page: 1, total_count: 2}When paginate_params and opts given are valid and when the queryable
passed is not a Ecto.Schema module, but an Ecto.Query.t.
iex> alias Rummage.Ecto.Hook.Paginate
iex> alias Rummage.Ecto.Employee
iex> paginate_params = %{
...> per_page: 1,
...> page: 1
...> }
iex> repo = Rummage.Ecto.Repo
iex> Ecto.Adapters.SQL.Sandbox.checkout(repo)
iex> repo.insert!(%Employee{first_name: "First"})
iex> repo.insert!(%Employee{first_name: "Second"})
iex> import Ecto.Query
iex> queryable = from u in Employee, where: u.first_name == "First"
iex> Paginate.format_params(queryable, paginate_params, [repo: repo])
%{max_page: 1, page: 1, per_page: 1, total_count: 1} Specs
run(Ecto.Query.t(), map()) :: Ecto.Query.t()
run(Ecto.Query.t(), map()) :: Ecto.Query.t()
This is the callback implementation of Rummage.Ecto.Hook.run/2.
Builds a paginate Ecto.Query.t on top of a given Ecto.Query.t variable
with given params.
Besides an Ecto.Query.t an Ecto.Schema module can also be passed as it
implements Ecto.Queryable
Params is a Map which is expected to have the keys per_page, page.
If an expected key isn't given, a Runtime Error is raised.
Examples
When an empty map is passed as params:
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> Paginate.run(Parent, %{})
** (RuntimeError) Error in params, No values given for keys: per_page, pageWhen a non-empty map is passed as params, but with a missing key:
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> Paginate.run(Parent, %{per_page: 10})
** (RuntimeError) Error in params, No values given for keys: pageWhen a valid map of params is passed with an Ecto.Schema module:
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> Paginate.run(Rummage.Ecto.Product, %{per_page: 10, page: 1})
#Ecto.Query<from p0 in Rummage.Ecto.Product, limit: ^10, offset: ^0>When the queryable passed is an Ecto.Query variable:
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> queryable = from u in "products"
#Ecto.Query<from p0 in "products">
iex> Paginate.run(queryable, %{per_page: 10, page: 2})
#Ecto.Query<from p0 in "products", limit: ^10, offset: ^10>More examples:
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> rummage = %{per_page: 1, page: 1}
iex> queryable = from u in "products"
#Ecto.Query<from p0 in "products">
iex> Paginate.run(queryable, rummage)
#Ecto.Query<from p0 in "products", limit: ^1, offset: ^0>
iex> alias Rummage.Ecto.Hook.Paginate
iex> import Ecto.Query
iex> rummage = %{per_page: 5, page: 2}
iex> queryable = from u in "products"
#Ecto.Query<from p0 in "products">
iex> Paginate.run(queryable, rummage)
#Ecto.Query<from p0 in "products", limit: ^5, offset: ^5>