Fob

Actions CI

A minimalistic keyset pagination library for Ecto queries

N.B.: you probably don’t want to use Fob. Fob makes a number of assumptions about the queries passed to it, such as:

Usage

Fob works primarily by composing Ecto queries with Ecto.Query.where/3 and Ecto.Query.limit/2. In general, the tracking of page breaks is left to any consuming library/application, but Fob provides a convenience tool which it uses internally for easy testing: Fob.Cursor.

A Fob.Cursor is a similar idea to a standard elixir Stream except that it does not represent an active connection to a resource (some but not all Elixir Streams open a process or port and therefore represent a connection to resource. This disallows some functionality which is desirable for Fob, such as Stream.split/2).

With the cursor, you may walk through the pages of a dataset with Fob.Cursor.next/1 and take multiple pages with Fob.Cursor.split/2

iex> alias Fob.Cursor
iex> import Ecto.Query, only: [order_by: 2]
iex> cursor = Cursor.new(order_by(MySchema, asc: :id), MyApp.Repo, _initial_pagination = nil, _page_size = 3)
#Fob.Cursor<...>
iex> {_records, cursor} = Cursor.next(cursor)
{[%{id: 1}, %{id: 2}, %{id: 3}], #Fob.Cursor<...>}
iex> {_records, cursor} = Cursor.next(cursor)
{[%{id: 4}, %{id: 5}, %{id: 6}], #Fob.Cursor<...>}
iex> {_records, cursor} = Cursor.split(cursor, 2)
{[%{id: 7}, %{id: 8}, %{id: 9}, %{id: 10}, %{id: 11}, %{id: 12}], #Fob.Cursor<...>}

Why?

Why build an incomplete and minimal keyset pagination library when there are already workable implementations in Paginator and Quarto? Fob was originally cut out of another library called Haste which we intend on open sourcing soon. In our setup, Haste only uses postgres and satisfies the above assumptions.

Installation

def deps do
  [
    {:fob, "~> 0.1"}
  ]
end

Check out the docs here: https://hexdocs.pm/fob