From dc1072de73ef549d7904d0b3d799f0a40c4b4db6 Mon Sep 17 00:00:00 2001 From: Nika Jukic Date: Tue, 26 Jul 2022 07:52:52 +0200 Subject: [PATCH] Add Pagy Countless paginator --- README.md | 16 ++++++--- .../query_builder/paginator/pagy_countless.rb | 29 +++++++++++++++ .../paginator/pagy_countless_spec.rb | 36 +++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 lib/jsonapi/query_builder/paginator/pagy_countless.rb create mode 100644 spec/jsonapi/query_builder/paginator/pagy_countless_spec.rb diff --git a/README.md b/README.md index f32f9b9..e26e1a8 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Or install it yourself as: ```ruby class UserQuery < Jsonapi::QueryBuilder::BaseQuery - ## pagination + ## pagination paginator Jsonapi::QueryBuilder::Paginator::Pagy # default paginator ## sorting @@ -62,9 +62,9 @@ pass the scoped collection to the `Jsonapi::QueryBuilder::BaseQuery` object. ### Pagination Pagination support is configurable using the `paginator` method to define the paginator. It defaults to the `Pagy` -paginator, a lightweight and fast paginator. Other paginators currently supported are `Kaminari` and an implementation -of keyset pagination. Before using these paginators we need to explicitly require the gems in our Gemfile and the -paginator file in question. Additionally one can implement it's own paginator by inheriting +paginator, a lightweight and fast paginator. Other paginators currently supported are `Kaminari`, `PagyCountless` and +an implementation of keyset pagination. Before using these paginators we need to explicitly require the gems in our +Gemfile and the paginator file in question. Additionally one can implement it's own paginator by inheriting from `Jsonapi::QueryBuilder::Paginator::BasePaginator`. The minimum required implementation is a `#paginate` method that receives page params and returns a page of the collection. It can return the pagination details as the second item of the returned array, that can be used in the serializer for pagination metadata. @@ -85,6 +85,14 @@ require "jsonapi/query_builder/paginator/keyset" paginator Jsonapi::QueryBuilder::Paginator::Keyset ``` +#### Using the Pagy Countless Paginator + +```ruby +require "jsonapi/query_builder/paginator/pagy_countless" + +paginator Jsonapi::QueryBuilder::Paginator::PagyCountless +``` + ### Sorting #### Ensuring deterministic results diff --git a/lib/jsonapi/query_builder/paginator/pagy_countless.rb b/lib/jsonapi/query_builder/paginator/pagy_countless.rb new file mode 100644 index 0000000..68d72c7 --- /dev/null +++ b/lib/jsonapi/query_builder/paginator/pagy_countless.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "pagy" +require "pagy/extras/items" +require "pagy/extras/countless" + +module Jsonapi + module QueryBuilder + module Paginator + class PagyCountless < BasePaginator + include ::Pagy::Backend + + def paginate(page_params) + @params = {page: page_params} + + pagination_details, records = pagy_countless(collection, page: page_params[:number], + items: page_params[:size], + outset: page_params[:offset]) + + [records, pagination_details] + end + + private + + attr_reader :params + end + end + end +end diff --git a/spec/jsonapi/query_builder/paginator/pagy_countless_spec.rb b/spec/jsonapi/query_builder/paginator/pagy_countless_spec.rb new file mode 100644 index 0000000..aa3858d --- /dev/null +++ b/spec/jsonapi/query_builder/paginator/pagy_countless_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require "jsonapi/query_builder/paginator/pagy_countless" + +RSpec.describe Jsonapi::QueryBuilder::Paginator::PagyCountless do + describe "#paginate" do + subject(:paginate) { pagy_paginator.paginate(number: 2, size: 20, offset: 3) } + + let(:pagy_paginator) { described_class.new(collection) } + let(:collection) { instance_double "collection" } + let(:paged_collection) { instance_double "paged-collection" } + let(:pagination_details) { instance_double Pagy, "pagination-details" } + + before do + allow(pagy_paginator).to receive(:pagy_countless).and_return([pagination_details, paged_collection]) + end + + it { is_expected.to be_an Array } + + it "returns the records and pagination details" do + expect(paginate).to eql [paged_collection, pagination_details] + end + + it "passes the collection and pagination params to pagy_countless method" do + paginate + + expect(pagy_paginator).to have_received(:pagy_countless).with(collection, page: 2, items: 20, outset: 3) + end + + it "sets the private params attribute reader used internally by pagy backend" do + paginate + + expect(pagy_paginator.send(:params)).to eql page: {number: 2, size: 20, offset: 3} + end + end +end