From d082729e4c6f4edbb73f01cbc6543d3d9f58faf5 Mon Sep 17 00:00:00 2001 From: renshuki Date: Fri, 19 Oct 2018 00:13:25 +0900 Subject: [PATCH] Added Elasticsearch Rails extra (#96) --- README.md | 3 +- docs/_layouts/default.html | 1 + docs/extras.md | 29 ++++---- docs/extras/elasticsearch_rails.md | 43 +++++++++++ lib/config/pagy.rb | 6 +- lib/pagy/extras/elasticsearch_rails.rb | 18 +++++ test/pagy/extras/elasticsearch_rails_test.rb | 75 ++++++++++++++++++++ 7 files changed, 159 insertions(+), 16 deletions(-) create mode 100644 docs/extras/elasticsearch_rails.md create mode 100644 lib/pagy/extras/elasticsearch_rails.rb create mode 100644 test/pagy/extras/elasticsearch_rails_test.rb diff --git a/README.md b/README.md index 4624d936c..ac87745f9 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,8 @@ Use the official extras, or write your own in just a few lines. Extras add speci ### Backend Extras - [array](http://ddnexus.github.io/pagy/extras/array): Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding -- [searchkick](http://ddnexus.github.io/pagy/extras/searchkick): Paginate `Searchkick::Results` objects efficiently, avoiding expensive oject-wrapping and without overriding +- [elasticsearch_rails](http://ddnexus.github.io/pagy/extras/elasticsearch_rails): Paginate `ElasticsearchRails::Results` objects efficiently, avoiding expensive object-wrapping and without overriding +- [searchkick](http://ddnexus.github.io/pagy/extras/searchkick): Paginate `Searchkick::Results` objects efficiently, avoiding expensive object-wrapping and without overriding ### Frontend Extras diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 9790de0f5..d71d977f9 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -36,6 +36,7 @@

{{ site.title | default: site.github.repository_name }}

Array

Bootstrap

Bulma

+

Elasticsearch Rails

Foundation

I18n

Items

diff --git a/docs/extras.md b/docs/extras.md index 1894f706d..e0ff01898 100644 --- a/docs/extras.md +++ b/docs/extras.md @@ -5,20 +5,21 @@ title: Extras Pagy comes with a few optional extensions/extras: -| Extra | Description | Links | -| :------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | -| `array` | Paginate arrays efficiently avoiding expensive array-wrapping and without overriding | [array.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/array.rb), [documentation](extras/array.md) | -| `bootstrap` | Nav, responsive and compact helpers and templates for the Bootstrap [pagination component](https://getbootstrap.com/docs/4.1/components/pagination) | [bootstrap.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/bootstrap.rb), [documentation](extras/bootstrap.md) | -| `bulma` | Nav, responsive and compact helpers and templates for the Bulma [pagination component](https://bulma.io/documentation/components/pagination) | [bulma.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/bulma.rb), [documentation](extras/bulma.md) | -| `foundation` | Nav, responsive and compact helpers and templates for the Foundation [pagination component](https://foundation.zurb.com/sites/docs/pagination.html) | [foundation.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/foundation.rb), [documentation](extras/foundation.md) | -| `i18n` | Use the `I18n` gem instead of the pagy implementation | [i18n.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/i81n.rb), [documentation](extras/i18n.md) | -| `items` | Allow the client to request a custom number of items per page with a ready to use selector UI | [items.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/items.rb), [documentation](extras/items.md) | -| `materialize` | Nav, responsive and compact helpers for the Materialize CSS [pagination component](https://materializecss.com/pagination.html) | [materialize.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/materialize.rb), [documentation](extras/materialize.md) | -| `navs` | Add responsive and compact generic/unstyled nav helpers | [navs.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/navs.rb), [documentation](extras/navs.md) | -| `out_of_range` | Allow for easy handling of out of range pages | [out_of_range.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/out_of_range.rb), [documentation](extras/out_of_range.md) | -| `searchkick` | Paginate arrays efficiently avoiding expensive array-wrapping and without overriding | [searchkick.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/searchkick.rb), [documentation](extras/searchkick.md) | -| `semantic` | Nav helpers for the Semantic UI CSS [pagination component](https://semantic-ui.com/collections/menu.html) | [semantic.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/semantic.rb), [documentation](extras/semantic.md) | -| `trim` | Remove the `page=1` param from links | [trim.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/trim.rb), [documentation](extras/trim.md) | +| Extra | Description | Links | +| :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `array` | Paginate arrays efficiently avoiding expensive array-wrapping and without overriding | [array.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/array.rb), [documentation](extras/array.md) | +| `bootstrap` | Nav, responsive and compact helpers and templates for the Bootstrap [pagination component](https://getbootstrap.com/docs/4.1/components/pagination) | [bootstrap.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/bootstrap.rb), [documentation](extras/bootstrap.md) | +| `bulma` | Nav, responsive and compact helpers and templates for the Bulma [pagination component](https://bulma.io/documentation/components/pagination) | [bulma.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/bulma.rb), [documentation](extras/bulma.md) | +| `elasticsearch_rails` | Paginate `elasticsearch_rails` gem results efficiently | [elasticsearch_rails.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/elasticsearch_rails.rb), [documentation](extras/elasticsearch_rails.md) | +| `foundation` | Nav, responsive and compact helpers and templates for the Foundation [pagination component](https://foundation.zurb.com/sites/docs/pagination.html) | [foundation.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/foundation.rb), [documentation](extras/foundation.md) | +| `i18n` | Use the `I18n` gem instead of the pagy implementation | [i18n.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/i81n.rb), [documentation](extras/i18n.md) | +| `items` | Allow the client to request a custom number of items per page with a ready to use selector UI | [items.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/items.rb), [documentation](extras/items.md) | +| `materialize` | Nav, responsive and compact helpers for the Materialize CSS [pagination component](https://materializecss.com/pagination.html) | [materialize.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/materialize.rb), [documentation](extras/materialize.md) | +| `navs` | Add responsive and compact generic/unstyled nav helpers | [navs.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/navs.rb), [documentation](extras/navs.md) | +| `out_of_range` | Allow for easy handling of out of range pages | [out_of_range.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/out_of_range.rb), [documentation](extras/out_of_range.md) | +| `searchkick` | Paginate arrays efficiently avoiding expensive array-wrapping and without overriding | [searchkick.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/searchkick.rb), [documentation](extras/searchkick.md) | +| `semantic` | Nav helpers for the Semantic UI CSS [pagination component](https://semantic-ui.com/collections/menu.html) | [semantic.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/semantic.rb), [documentation](extras/semantic.md) | +| `trim` | Remove the `page=1` param from links | [trim.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/trim.rb), [documentation](extras/trim.md) | ## Synopsys diff --git a/docs/extras/elasticsearch_rails.md b/docs/extras/elasticsearch_rails.md new file mode 100644 index 000000000..243967e32 --- /dev/null +++ b/docs/extras/elasticsearch_rails.md @@ -0,0 +1,43 @@ +--- +title: Elasticsearch Rails +--- +# Elasticsearch Rails Extra + +Paginate `ElasticsearchRails::Results` objects efficiently avoiding expensive object-wrapping and without overriding. + +## Synopsys + +See [extras](../extras.md) for general usage info. + +In a controller: + +```ruby +def search + @pagy, @articles = pagy_elasticsearch_rails(Article.search(params[:q]).records, items: 10) + + render action: "index" +end + +# independently paginate some other collections as usual +@pagy_b, @records = pagy(some_scope, ...) +``` + +## Files + +This extra is composed of 1 file: + +- [elasticsearch_rails.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/elasticsearch_rails.rb) + +## Methods + +This extra adds the `pagy_elasticsearch_rails` method to the `Pagy::Backend` to be used in place (or in parallel) of the `pagy` method when you have to paginate a `ElasticsearchRails::Results` object. It also adds a `pagy_elasticsearch_rails_get_variables` sub-method, used for easy customization of variables by overriding. + +**Notice**: there is no `pagy_elasticsearch_rails_get_items` method to override, since the items are fetched directly by Elasticsearch Rails. + +### pagy_elasticsearch_rails(Model.search(...), vars=nil) + +This method is the same as the generic `pagy` method, but specialized for Elasticsearch Rails. (see the [pagy doc](../api/backend.md#pagycollection-varsnil)) + +### pagy_elastic_search_rails_get_vars(array) + +This sub-method is the same as the `pagy_get_vars` sub-method, but it is called only by the `pagy_elasticsearch_rails` method. (see the [pagy_get_vars doc](../api/backend.md#pagy_get_varscollection-vars)). diff --git a/lib/config/pagy.rb b/lib/config/pagy.rb index b2c6f65ce..30283fdb0 100644 --- a/lib/config/pagy.rb +++ b/lib/config/pagy.rb @@ -12,7 +12,11 @@ # See https://ddnexus.github.io/pagy/extras/array # require 'pagy/extras/array' -# Searchkick: Paginate `Searchkick::Results` objects efficiently, avoiding expensive oject-wrapping and without overriding. +# Elasticsearch Rails: Paginate `ElasticsearchRails::Results` objects efficiently, avoiding expensive object-wrapping and without overriding. +# See https://ddnexus.github.io/pagy/extras/elasticsearch_rails +# require 'pagy/extras/elasticsearch_rails' + +# Searchkick: Paginate `Searchkick::Results` objects efficiently, avoiding expensive object-wrapping and without overriding. # See https://ddnexus.github.io/pagy/extras/searchkick # require 'pagy/extras/searchkick' diff --git a/lib/pagy/extras/elasticsearch_rails.rb b/lib/pagy/extras/elasticsearch_rails.rb new file mode 100644 index 000000000..99abda63e --- /dev/null +++ b/lib/pagy/extras/elasticsearch_rails.rb @@ -0,0 +1,18 @@ +# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/elasticsearch_rails + +class Pagy + # Add specialized backend methods to paginate ElasticsearchRails::Results + module Backend ; private + # Return Pagy object and items + def pagy_elasticsearch_rails(results, vars={}) + pagy = Pagy.new(pagy_elasticsearch_rails_get_vars(results, vars)) + return pagy, results.offset(pagy.offset).limit(pagy.items) + end + + def pagy_elasticsearch_rails_get_vars(results, vars) + # Return the merged variables to initialize the Pagy object + { count: results.total, + page: (params[:page] || 1)}.merge!(vars) + end + end +end diff --git a/test/pagy/extras/elasticsearch_rails_test.rb b/test/pagy/extras/elasticsearch_rails_test.rb new file mode 100644 index 000000000..37d26caea --- /dev/null +++ b/test/pagy/extras/elasticsearch_rails_test.rb @@ -0,0 +1,75 @@ +require_relative '../../test_helper' +require 'pagy/extras/elasticsearch_rails' + +SingleCov.covered! + +describe Pagy::Backend do + + let(:backend) { TestController.new } + + class ElasticsearchRails + class Results + def initialize(params); @params = params; end + def total; 1000; end + def offset(value); self; end + def limit(value); 25; end + def page + @params[:page] || 1 + end + end + end + + describe "#pagy_elasticsearch_rails" do + + before do + @collection = ElasticsearchRails::Results.new(backend.params) + end + + it 'paginates with defaults' do + pagy, _items = backend.send(:pagy_elasticsearch_rails, @collection) + pagy.must_be_instance_of Pagy + pagy.count.must_equal 1000 + pagy.items.must_equal 20 # Pagy default + pagy.page.must_equal backend.params[:page] + end + + it 'paginates with vars' do + pagy, _items = backend.send(:pagy_elasticsearch_rails, @collection, link_extra: 'X') + pagy.must_be_instance_of Pagy + pagy.count.must_equal 1000 + pagy.items.must_equal 20 # Pagy default + pagy.vars[:link_extra].must_equal 'X' + end + + end + + describe "#pagy_elasticsearch_rails_get_vars" do + + before do + @collection = ElasticsearchRails::Results.new(backend.params) + end + + it 'gets defaults' do + vars = {} + merged = backend.send :pagy_elasticsearch_rails_get_vars, @collection, vars + merged.keys.must_include :count + merged.keys.must_include :page + merged[:count].must_equal 1000 + merged[:items].must_be_nil + merged[:page].must_equal 3 + end + + it 'gets vars' do + vars = { items: 25, link_extra: 'X' } + merged = backend.send :pagy_elasticsearch_rails_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