Skip to content

Instantly share code, notes, and snippets.

@goromlagche
Last active December 8, 2023 13:01
Show Gist options
  • Select an option

  • Save goromlagche/d2075bc8ad8fedd3a9930cd9f3c38ae4 to your computer and use it in GitHub Desktop.

Select an option

Save goromlagche/d2075bc8ad8fedd3a9930cd9f3c38ae4 to your computer and use it in GitHub Desktop.

Revisions

  1. goromlagche revised this gist Jan 26, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion pagination.rb
    Original file line number Diff line number Diff line change
    @@ -52,7 +52,7 @@ def pagination_window

    def pagination_url(direction:)
    return "" if @seek == false && direction == @params[:direction]
    return "" if @params[:cursor_created_at].blank? && direction == "prev"
    return "" if @params[:cursor_created_at].blank? && direction == "prev" # first page

    cursor = direction == "prev" ? paginated_records.first : paginated_records.last

  2. goromlagche created this gist Jan 26, 2022.
    90 changes: 90 additions & 0 deletions pagination.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    # frozen_string_literal: true
    # drop this file in app/lib/pagination.rb

    module Pagination
    DEFAULT_PAGE_LIMIT = 10

    def pages(records:, url:)
    paginate = Paginate.new(records: records,
    url: url,
    limit: limit,
    params: pagination_params)
    paginate.pages
    end

    def limit
    return self.class::PAGE_LIMIT if defined? self.class::PAGE_LIMIT

    DEFAULT_PAGE_LIMIT
    end

    def pagination_params
    params.permit(:cursor_created_at, :direction)
    end


    class Paginate
    def initialize(records:, url:, limit:, params:)
    @records = records
    @url = url
    @limit = limit
    @params = params
    end

    def pages
    {
    records: paginated_records,
    next_url: pagination_url(direction: "next"),
    prev_url: pagination_url(direction: "prev"),
    }
    end

    private
    def pagination_window
    return if @params[:cursor_created_at].blank?

    if @params[:direction] == "prev"
    @records.arel_table[:created_at].gt(@params[:cursor_created_at])
    else
    @records.arel_table[:created_at].lt(@params[:cursor_created_at])
    end
    end

    def pagination_url(direction:)
    return "" if @seek == false && direction == @params[:direction]
    return "" if @params[:cursor_created_at].blank? && direction == "prev"

    cursor = direction == "prev" ? paginated_records.first : paginated_records.last

    uri = URI(@url)
    params = Hash[URI.decode_www_form(uri.query || "")]
    .merge("cursor_created_at" => cursor.created_at.iso8601(6), # PG default is 6
    "direction" => direction)
    uri.query = URI.encode_www_form(params)
    uri
    end


    def paginated_records
    return @paginated_records if defined? @paginated_records

    @paginated_records = @records
    .unscope(:order)
    .where(pagination_window)
    .order(created_at: order_direction)
    .limit(@limit + 1)
    .to_a

    @seek = (@paginated_records.size > @limit)
    @paginated_records.pop if @seek == true
    @paginated_records.reverse! if @params[:direction] == "prev"
    @paginated_records
    end

    def order_direction
    return :asc if @params[:direction] == "prev"

    :desc
    end
    end
    end
    35 changes: 35 additions & 0 deletions records.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,35 @@
    class Records extends React.Component {
    static propTypes = {
    recordsUrl: PropTypes.string
    };

    componentDidMount() {
    this.fetchRecords(this.props.recordsUrl);
    }

    state = {
    records: [],
    prevUrl: "",
    nextUrl: ""
    };

    fetchRecords = url => {
    fetch(url)
    .then(data => {
    if (data.ok) {
    return data.json();
    }
    throw new Error("Network error!");
    })
    .then(data => {
    this.setState({
    records: data.records,
    nextUrl: data.next_url,
    prevUrl: data.prev_url,
    });
    })
    .catch(err => console.log("Error: " + err));
    };
    ...
    ...
    ...
    18 changes: 18 additions & 0 deletions records_controller.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    module Api
    module V1
    class RecordsController < BaseApiController
    include Pagination

    def index
    render json: pages(records: records, url: api_v1_records_path),
    except: [:updated_at],
    status: :ok
    end

    private
    def records
    Records.with_attached_image
    end
    end
    end
    end