Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for cursor custom conversion #62

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion lib/paginator/cursor.ex
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
defmodule Paginator.Cursor do
@moduledoc false

def decode(nil), do: nil

def decode(encoded_cursor) do
encoded_cursor
|> Base.url_decode64!()
|> :erlang.binary_to_term([:safe])
|> Enum.map(&Paginator.Cursor.Decode.convert/1)
end

def encode(values) when is_list(values) do
values
|> Enum.map(&Paginator.Cursor.Encode.convert/1)
|> :erlang.term_to_binary()
|> Base.url_encode64()
end
Expand All @@ -19,3 +20,23 @@ defmodule Paginator.Cursor do
encode([value])
end
end

defprotocol Paginator.Cursor.Encode do
@fallback_to_any true

def convert(term)
end

defprotocol Paginator.Cursor.Decode do
@fallback_to_any true

def convert(term)
end

defimpl Paginator.Cursor.Encode, for: Any do
def convert(term), do: term
end

defimpl Paginator.Cursor.Decode, for: Any do
def convert(term), do: term
end
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule Paginator.Mixfile do
elixirc_paths: elixirc_paths(Mix.env()),
build_embedded: Mix.env() == :prod,
start_permanent: Mix.env() == :prod,
consolidate_protocols: Mix.env() != :test,
deps: deps(),

# Hex
Expand Down
33 changes: 33 additions & 0 deletions test/paginator/cursor_test.exs
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
defmodule Paginator.CursorTest do
use ExUnit.Case, async: true

defmodule MYTEST1 do
defstruct id: nil
end

defmodule MYTEST2 do
defstruct id: nil
end

defimpl Paginator.Cursor.Encode, for: MYTEST1 do
def convert(term), do: {:m1, term.id}
end

defimpl Paginator.Cursor.Decode, for: Tuple do
def convert({:m1, id}), do: %MYTEST1{id: id}
end

alias Paginator.Cursor

describe "encoding and decoding terms" do
test "cursor for struct with custom implementation is shorter" do
cursor1 = Cursor.encode([%MYTEST1{id: 1}])

assert Cursor.decode(cursor1) == [%MYTEST1{id: 1}]

cursor2 = Cursor.encode([%MYTEST2{id: 1}])

assert Cursor.decode(cursor2) == [%MYTEST2{id: 1}]
assert bit_size(cursor1) < bit_size(cursor2)
end

test "list of lists " do
cursor = Cursor.encode([[1]])

assert Cursor.decode(cursor) == [[1]]
end

test "it wraps terms into lists" do
cursor = Cursor.encode(1)

Expand Down