Skip to content

Instantly share code, notes, and snippets.

@parallel588
Forked from edipox/jsonapi_paginator.ex
Created May 16, 2022 17:24
Show Gist options
  • Select an option

  • Save parallel588/5e469d0f9a6305c6e471427d9e56faa8 to your computer and use it in GitHub Desktop.

Select an option

Save parallel588/5e469d0f9a6305c6e471427d9e56faa8 to your computer and use it in GitHub Desktop.

Revisions

  1. @edipox edipox revised this gist Mar 8, 2018. 1 changed file with 29 additions and 55 deletions.
    84 changes: 29 additions & 55 deletions jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -1,61 +1,35 @@
    defmodule JsonApi.Paginator do
    # ...
    # ...

    alias SomeProject.Repo

    import Ecto.Query

    @doc """
    Helper function used to paginate index queries
    """
    @spec paginate(conn :: Plug.Conn.t(), page_params :: map, query :: module) :: Plug.Conn.t()
    def paginate(conn, page_params, query) do
    page_number = validate_int(page_params["number"], 1, -1)
    page_size = validate_int(page_params["size"], default_page_size(), maximum_page_size())
    # Paginate
    @spec handle_pagination(conn :: Plug.Conn.t(), page :: number | atom, page_size :: number | atom, query :: module) ::
    Plug.Conn.t()
    defp handle_pagination(conn, page, page_size, query) do
    config = %Scrivener.Config{
    module: Repo,
    page_number: page,
    page_size: page_size,
    options: [total_entries: total_entries(query)]
    }

    handle_pagination(conn, page_number, page_size, query)
    end
    query |> Scrivener.paginate(config)
    end

    # Handle invalid page params
    @spec handle_pagination(conn :: Plug.Conn.t(), page :: number | atom, page_size :: number | atom, query :: module) :: Plug.Conn.t()
    defp handle_pagination(conn, :error, _page_size, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[number] has to be positive number.")
    end
    # Retrieves the estimated record count
    @spec total_entries(query :: module) :: number
    defp total_entries(query) do
    table_name = table_name(query)

    defp handle_pagination(conn, _page, :error, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[size] has to be positive number (maximum value is #{maximum_page_size()}).")
    end
    {:ok, result} =
    Ecto.Adapters.SQL.query(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname=$1", [table_name])

    # Paginate
    defp handle_pagination(conn, page, page_size, query) do
    config = %Scrivener.Config{
    module: Repo,
    page_number: page, page_size: page_size,
    options: [total_entries: total_entries(query)]
    }
    query |> Scrivener.paginate(config)
    end
    result.rows |> List.first() |> List.first()
    end

    # Retrieves the estimated record count
    @spec total_entries(query :: module) :: number
    defp total_entries(query) do
    table_name = table_name(query)
    {:ok, result} = Ecto.Adapters.SQL.query(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname=$1", [table_name])
    result.rows |> List.first |> List.first
    end
    # Determines the table name based on a given query
    @spec table_name(query :: module) :: module
    defp table_name(query) do
    module_from_query(query).__schema__(:source)
    end

    # Determines the table name based on a given query
    @spec table_name(query :: module) :: module
    defp table_name(query) do
    module(query).__schema__(:source)
    end

    # Retrieves the model module from a given query
    @spec module(module :: module) :: module
    defp module(%{from: {_table, module}}), do: module
    defp module(module), do: module

    # ...
    # ...
    end
    # Retrieves the model module from a given query
    @spec module_from_query(module :: module) :: module
    defp module_from_query(%{from: {_table, module}}), do: module
    defp module_from_query(module), do: module
  2. @edipox edipox revised this gist Mar 8, 2018. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -32,14 +32,14 @@ defmodule JsonApi.Paginator do
    config = %Scrivener.Config{
    module: Repo,
    page_number: page, page_size: page_size,
    options: [total_entries: total_entries(conn, query)]
    options: [total_entries: total_entries(query)]
    }
    query |> Scrivener.paginate(config)
    end

    # Retrieves the estimated record count
    @spec total_entries(conn :: Plug.Conn.t(), query :: module) :: number
    defp total_entries(_conn, query) do
    @spec total_entries(query :: module) :: number
    defp total_entries(query) do
    table_name = table_name(query)
    {:ok, result} = Ecto.Adapters.SQL.query(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname=$1", [table_name])
    result.rows |> List.first |> List.first
  3. @edipox edipox revised this gist Jan 20, 2018. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,4 @@
    defmodule JsonApi.Paginator do

    # ...
    # ...

  4. @edipox edipox revised this gist Jan 20, 2018. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,12 @@
    defmodule JsonApi.Paginator do
    import Ecto.Query

    # ...
    # ...

    alias SomeProject.Repo

    import Ecto.Query

    @doc """
    Helper function used to paginate index queries
    """
    @@ -51,4 +56,7 @@ defmodule JsonApi.Paginator do
    @spec module(module :: module) :: module
    defp module(%{from: {_table, module}}), do: module
    defp module(module), do: module

    # ...
    # ...
    end
  5. @edipox edipox revised this gist Jan 20, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ defmodule JsonApi.Paginator do
    module(query).__schema__(:source)
    end

    # Retrieves the model module from a given query
    # Retrieves the model module from a given query
    @spec module(module :: module) :: module
    defp module(%{from: {_table, module}}), do: module
    defp module(module), do: module
  6. @edipox edipox revised this gist Jan 20, 2018. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -5,6 +5,7 @@ defmodule JsonApi.Paginator do
    @doc """
    Helper function used to paginate index queries
    """
    @spec paginate(conn :: Plug.Conn.t(), page_params :: map, query :: module) :: Plug.Conn.t()
    def paginate(conn, page_params, query) do
    page_number = validate_int(page_params["number"], 1, -1)
    page_size = validate_int(page_params["size"], default_page_size(), maximum_page_size())
    @@ -13,9 +14,11 @@ defmodule JsonApi.Paginator do
    end

    # Handle invalid page params
    @spec handle_pagination(conn :: Plug.Conn.t(), page :: number | atom, page_size :: number | atom, query :: module) :: Plug.Conn.t()
    defp handle_pagination(conn, :error, _page_size, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[number] has to be positive number.")
    end

    defp handle_pagination(conn, _page, :error, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[size] has to be positive number (maximum value is #{maximum_page_size()}).")
    end
    @@ -31,18 +34,21 @@ defmodule JsonApi.Paginator do
    end

    # Retrieves the estimated record count
    @spec total_entries(conn :: Plug.Conn.t(), query :: module) :: number
    defp total_entries(_conn, query) do
    table_name = table_name(query)
    {:ok, result} = Ecto.Adapters.SQL.query(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname=$1", [table_name])
    result.rows |> List.first |> List.first
    end

    # Determines the table name based on a given query
    @spec table_name(query :: module) :: module
    defp table_name(query) do
    module(query).__schema__(:source)
    end

    # Retrieves the model module from a given query
    # Retrieves the model module from a given query
    @spec module(module :: module) :: module
    defp module(%{from: {_table, module}}), do: module
    defp module(module), do: module
    end
  7. @edipox edipox revised this gist Jan 13, 2018. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -12,14 +12,15 @@ defmodule JsonApi.Paginator do
    handle_pagination(conn, page_number, page_size, query)
    end

    # Handle invalid page params
    defp handle_pagination(conn, :error, _page_size, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[number] has to be positive number.")
    end

    defp handle_pagination(conn, _page, :error, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[size] has to be positive number (maximum value is #{maximum_page_size()}).")
    end

    # Paginate
    defp handle_pagination(conn, page, page_size, query) do
    config = %Scrivener.Config{
    module: Repo,
  8. @edipox edipox created this gist Jan 13, 2018.
    47 changes: 47 additions & 0 deletions jsonapi_paginator.ex
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    defmodule JsonApi.Paginator do
    import Ecto.Query
    alias SomeProject.Repo

    @doc """
    Helper function used to paginate index queries
    """
    def paginate(conn, page_params, query) do
    page_number = validate_int(page_params["number"], 1, -1)
    page_size = validate_int(page_params["size"], default_page_size(), maximum_page_size())

    handle_pagination(conn, page_number, page_size, query)
    end

    defp handle_pagination(conn, :error, _page_size, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[number] has to be positive number.")
    end

    defp handle_pagination(conn, _page, :error, _query) do
    Response.send_error_resp(conn, :bad_request, "Invalid page value", "page[size] has to be positive number (maximum value is #{maximum_page_size()}).")
    end

    defp handle_pagination(conn, page, page_size, query) do
    config = %Scrivener.Config{
    module: Repo,
    page_number: page, page_size: page_size,
    options: [total_entries: total_entries(conn, query)]
    }
    query |> Scrivener.paginate(config)
    end

    # Retrieves the estimated record count
    defp total_entries(_conn, query) do
    table_name = table_name(query)
    {:ok, result} = Ecto.Adapters.SQL.query(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname=$1", [table_name])
    result.rows |> List.first |> List.first
    end

    # Determines the table name based on a given query
    defp table_name(query) do
    module(query).__schema__(:source)
    end

    # Retrieves the model module from a given query
    defp module(%{from: {_table, module}}), do: module
    defp module(module), do: module
    end