diff --git a/docs/extras/searchkick.md b/docs/extras/searchkick.md new file mode 100644 index 000000000..34c21763c --- /dev/null +++ b/docs/extras/searchkick.md @@ -0,0 +1,56 @@ +--- +title: Searchkick +--- +# Searchkick Extra + +This extra adds a specialized pagination for `Searchkick::Results` objects without the need to override the `pagy_get_items` in your controller. + +The `Searchkick::Results` object has already done pagination calculations, we just need to tell Pagy how to read page and total values. It is expected that you let Searchkick handle the `page` and `per_page` variables instead of providing those values as options to Pagy. + +## Synopsys + +See [extras](../extras.md) for general usage info. + +In a controller: + +```ruby +@pagy_s, @models = pagy_searchkick( + Model.search("*", + { + where: { + ... + }, + fields: [...], + select: [...], + load: true, + page: params[:page], + per_page: 25 + } + ) + , + ... + ) + +# independently paginate some other collections as usual +@pagy_b, @records = pagy(some_scope, ...) +``` + +## Files + +This extra is composed of 1 file: + +- [searchkick.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/searchkick.rb) + +## Methods + +This extra adds the `pagy_searchkick` method to the `Pagy::Backend` to be used in place (or in parallel) of the `pagy` method when you have to paginate a `Searchkick::Results` object. It also adds a `pagy_searchkick_get_variables` sub-method, used for easy customization of variables by overriding. + +**Notice**: there is no `pagy_searchkick_get_items` method to override, since the items are fetched directly by Searchkick. + +### pagy_searchkick(Model.search(...), vars=nil) + +This method is the same as the generic `pagy` method, but specialized for Searchkick. (see the [pagy doc](../api/backend.md#pagycollection-varsnil)) + +### pagy_searchkick_get_vars(array) + +This sub-method is the same as the `pagy_get_vars` sub-method, but it is called only by the `pagy_searchkick` method. (see the [pagy_get_vars doc](../api/backend.md#pagy_get_varscollection-vars)). diff --git a/lib/pagy/extras/searchkick.rb b/lib/pagy/extras/searchkick.rb new file mode 100644 index 000000000..e3a944650 --- /dev/null +++ b/lib/pagy/extras/searchkick.rb @@ -0,0 +1,19 @@ +# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick + +class Pagy + # Add specialized backend methods to paginate Searchkick::Results + module Backend ; private + # Return Pagy object and items + def pagy_searchkick(results, vars={}) + pagy = Pagy.new(pagy_searchkick_get_vars(results, vars)) + return pagy, results + end + + def pagy_searchkick_get_vars(results, vars) + # Return the merged variables to initialize the Pagy object + { count: results.total_count, + page: results.options[:page], + items: results.options[:per_page] }.merge!(vars) + end + end +end diff --git a/test/pagy/extras/searchkick_test.rb b/test/pagy/extras/searchkick_test.rb new file mode 100644 index 000000000..d48c2676a --- /dev/null +++ b/test/pagy/extras/searchkick_test.rb @@ -0,0 +1,76 @@ +require_relative '../../test_helper' +require 'pagy/extras/searchkick' + +SingleCov.covered! + +describe Pagy::Backend do + + let(:backend) { TestController.new } + + class Searchkick + class Results + def initialize(params); @params = params; end + def total_count; 1000; end + def options + { + page: @params[:page] || 1, + per_page: 25 + } + end + end + end + + describe "#pagy_searchkick" do + + before do + @collection = Searchkick::Results.new(backend.params) + end + + it 'paginates with defaults' do + pagy, _items = backend.send(:pagy_searchkick, @collection) + pagy.must_be_instance_of Pagy + pagy.count.must_equal 1000 + pagy.items.must_equal 25 + pagy.page.must_equal backend.params[:page] + end + + it 'paginates with vars' do + pagy, _items = backend.send(:pagy_searchkick, @collection, link_extra: 'X') + pagy.must_be_instance_of Pagy + pagy.count.must_equal 1000 + pagy.items.must_equal 25 + pagy.vars[:link_extra].must_equal 'X' + end + + end + + describe "#pagy_searchkick_get_vars" do + + before do + @collection = Searchkick::Results.new(backend.params) + end + + it 'gets defaults' do + vars = {} + merged = backend.send :pagy_searchkick_get_vars, @collection, vars + merged.keys.must_include :count + merged.keys.must_include :page + merged[:count].must_equal 1000 + merged[:items].must_equal 25 + merged[:page].must_equal 3 + end + + it 'gets vars' do + vars = {link_extra: 'X'} + merged = backend.send :pagy_searchkick_get_vars, @collection, vars + merged.keys.must_include :count + merged.keys.must_include :page + merged.keys.must_include :link_extra + merged[:count].must_equal 1000 + merged[:items].must_equal 25 + merged[:link_extra].must_equal 'X' + end + + end + +end