From f0e0d416ff97b7a0bfdf18d8e8e03dada9156e8f Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Mon, 5 Apr 2021 15:30:16 +0700
Subject: [PATCH 01/17] removed require for minitest/reporters
---
test/test_helper.rb | 5 -----
1 file changed, 5 deletions(-)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 060f5445c..ece1e0e08 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -22,8 +22,3 @@
require_relative 'mock_helpers/view'
require_relative 'mock_helpers/controller'
require "minitest/autorun"
-
-unless ENV['TRAVIS']
- require 'minitest/reporters'
- MiniTest::Reporters.use!
-end
From a8060b1d9367e21985fd92a01fcd9fca4e1e736a Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Mon, 5 Apr 2021 15:31:40 +0700
Subject: [PATCH 02/17] fixed doc typos
---
docs/api/backend.md | 2 +-
docs/api/frontend.md | 2 +-
docs/index.md | 2 +-
{docker => pagy-on-docker}/README.md | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
rename {docker => pagy-on-docker}/README.md (96%)
diff --git a/docs/api/backend.md b/docs/api/backend.md
index b46c99fb1..96d4f9d17 100644
--- a/docs/api/backend.md
+++ b/docs/api/backend.md
@@ -32,7 +32,7 @@ end
All the methods in this module are prefixed with the `"pagy_"` string, to avoid any possible conflict with your own methods when you include the module in your controller. They are also all private, so they will not be available as actions. The methods prefixed with the `"pagy_get_"` string are sub-methods/getter methods that are intended to be overridden, not used directly.
-Please, keep in mind that overriding any method is very easy with Pagy. Indeed you can do it right where you are using it: no need of monkey-patching or perform any tricky gymnic.
+Please, keep in mind that overriding any method is very easy with Pagy. Indeed you can do it right where you are using it: no need of monkey-patching or perform any tricky gymmickry.
### pagy(collection, vars=nil)
diff --git a/docs/api/frontend.md b/docs/api/frontend.md
index fe358f103..c8275928c 100644
--- a/docs/api/frontend.md
+++ b/docs/api/frontend.md
@@ -30,7 +30,7 @@ use some of its method in some view:
All the methods in this module are prefixed with the `"pagy_"` string in order to avoid any possible conflict with your own methods when you include the module in your helper. The methods prefixed with the `"pagy_get_"` string are sub-methods/getter methods that are intended to be overridden and not used directly.
-Please, keep in mind that overriding any method is very easy with Pagy. Indeed you can do it right where you are using it: no need of monkey-patching or tricky gymnic.
+Please, keep in mind that overriding any method is very easy with Pagy. Indeed you can do it right where you are using it: no need of monkey-patching or tricky gymmickry.
### pagy_nav(pagy)
diff --git a/docs/index.md b/docs/index.md
index dd1028ec8..0926634c6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -41,6 +41,6 @@ You could even use it directly (without using any other Pagy code) in a small pa
## Really easy to customize
-If options and configuration are not enough, you have a few specialized [extras](extras.md), and if all that is still not enough, any other special customization is at most _one step far_ from your own code. All the Pagy helpers are contained in 2 plain modules with no nesting. You include them in your code, so you can override any method right where you use it: no tricky gymnic required.
+If options and configuration are not enough, you have a few specialized [extras](extras.md), and if all that is still not enough, any other special customization is at most _one step far_ from your own code. All the Pagy helpers are contained in 2 plain modules with no nesting. You include them in your code, so you can override any method right where you use it: no tricky gymmickry required.
What could be easier?
diff --git a/docker/README.md b/pagy-on-docker/README.md
similarity index 96%
rename from docker/README.md
rename to pagy-on-docker/README.md
index 6cfed3b55..17323641f 100644
--- a/docker/README.md
+++ b/pagy-on-docker/README.md
@@ -8,7 +8,7 @@ You can use it to develop changes, run tests and check a live preview of the doc
The pagy docker environment has been designed to be useful for developing:
-- It provides the infrastructure required (right version of ruby, jekyll server, env variable, tests, etc.) without the hassle to install and maintain anything in your system
+- It provides the infrastructure required (right version of ruby, jekyll server, env variables, tests, etc.) without the hassle to install and maintain anything in your system
- The local `pagy` dir is mounted at the container dir `/opt/project` so you can edit the files in your local pagy dir or in the container: they are the same files.
- The gems are installed in the container `BUNDLE_PATH=/usr/local/bundle` and that dir is `chown`ed to your user, and mounted as the docker volume `pagy_bundle`. You can use the `bundle` command and it will be persisted in the volume, no need to rebuild the image nor pollute your own system.
- Your container user `HOME` is preserved in the `pagy_user_home` volume, so you can even get back to the shell history in future sessions.
From 8cd25d25346d5c990abcc7b2d16feac265a54424 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Mon, 5 Apr 2021 15:32:45 +0700
Subject: [PATCH 03/17] renamed docker > pagy-on-docker
---
{docker => pagy-on-docker}/docker-compose.yml | 4 ++--
{docker => pagy-on-docker}/pagy-jekyll.dockerfile | 0
{docker => pagy-on-docker}/pagy.dockerfile | 0
3 files changed, 2 insertions(+), 2 deletions(-)
rename {docker => pagy-on-docker}/docker-compose.yml (94%)
rename {docker => pagy-on-docker}/pagy-jekyll.dockerfile (100%)
rename {docker => pagy-on-docker}/pagy.dockerfile (100%)
diff --git a/docker/docker-compose.yml b/pagy-on-docker/docker-compose.yml
similarity index 94%
rename from docker/docker-compose.yml
rename to pagy-on-docker/docker-compose.yml
index 3d6cab591..4fee04e96 100644
--- a/docker/docker-compose.yml
+++ b/pagy-on-docker/docker-compose.yml
@@ -1,5 +1,5 @@
-# Basic docker development environment
-# it will keep the installed gems and HOME in the pagy_bundle and pagy_user_home docker volumes
+# Basic pagy-on-docker development environment
+# it will keep the installed gems and HOME in the pagy_bundle and pagy_user_home pagy-on-docker volumes
# the gh-pages service will be updating a live preview for the documentation
diff --git a/docker/pagy-jekyll.dockerfile b/pagy-on-docker/pagy-jekyll.dockerfile
similarity index 100%
rename from docker/pagy-jekyll.dockerfile
rename to pagy-on-docker/pagy-jekyll.dockerfile
diff --git a/docker/pagy.dockerfile b/pagy-on-docker/pagy.dockerfile
similarity index 100%
rename from docker/pagy.dockerfile
rename to pagy-on-docker/pagy.dockerfile
From 3a9e70fc982dbc459da46ebec06b2245ef3caafd Mon Sep 17 00:00:00 2001
From: Jesse
Date: Thu, 8 Apr 2021 20:46:45 +1200
Subject: [PATCH 04/17] Fix extra i18n namespacing (#293)
* Add a test that looks at i18n working in Modules included
* Demonstrates https://github.com/ddnexus/pagy/issues/290
* Correct name collision with I18n with UseI18n
(fixes #290)
---
lib/pagy/extras/i18n.rb | 4 ++--
test/mock_helpers/application_helper.rb | 8 ++++++++
test/pagy/extras/i18n_test.rb | 6 ++++++
3 files changed, 16 insertions(+), 2 deletions(-)
create mode 100644 test/mock_helpers/application_helper.rb
diff --git a/lib/pagy/extras/i18n.rb b/lib/pagy/extras/i18n.rb
index 2a16f3717..d125855a7 100644
--- a/lib/pagy/extras/i18n.rb
+++ b/lib/pagy/extras/i18n.rb
@@ -10,10 +10,10 @@ module Frontend
Pagy::I18n.clear.instance_eval { undef :load; undef :t } # unload the pagy default constant for efficiency
- module I18n
+ module UseI18nGem
def pagy_t(key, **opts) = ::I18n.t(key, **opts)
end
- prepend I18n
+ prepend UseI18nGem
end
end
diff --git a/test/mock_helpers/application_helper.rb b/test/mock_helpers/application_helper.rb
new file mode 100644
index 000000000..b742b8505
--- /dev/null
+++ b/test/mock_helpers/application_helper.rb
@@ -0,0 +1,8 @@
+module ApplicationHelper
+ include Pagy::Frontend
+
+ def any_method_name()
+ I18n.t("test")
+ end
+
+end
\ No newline at end of file
diff --git a/test/pagy/extras/i18n_test.rb b/test/pagy/extras/i18n_test.rb
index e507d69f6..4975a362d 100644
--- a/test/pagy/extras/i18n_test.rb
+++ b/test/pagy/extras/i18n_test.rb
@@ -7,11 +7,17 @@
SimpleCov.command_name 'i18n' if ENV['RUN_SIMPLECOV'] == 'true'
+require_relative '../../mock_helpers/application_helper'
+include ApplicationHelper
+
describe Pagy::Frontend do
let(:view) { MockView.new }
describe "#pagy_t with I18n" do
+ it 'works with an included Module' do
+ ApplicationHelper.any_method_name()
+ end
it 'pluralizes' do
_(view.pagy_t('pagy.nav.prev')).must_equal "‹ Prev"
From b2aaa01cd3d65715201cf46064f1ebb01f7bcda2 Mon Sep 17 00:00:00 2001
From: szTheory
Date: Thu, 8 Apr 2021 08:51:54 +0000
Subject: [PATCH 05/17] README: fix typo (#289) [ci-skip]
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0dd29a099..fb30cae96 100644
--- a/README.md
+++ b/README.md
@@ -137,7 +137,7 @@ Besides the classic pagination offered by the `pagy_nav` helpers, you can use a
### Related Projects
-- [pagy-cursor](https://github.com/Uysim/pagy-cursor) An early stage proget that implements cursor pagination for AR
+- [pagy-cursor](https://github.com/Uysim/pagy-cursor) An early stage project that implements cursor pagination for AR
## Resources
From 3eef450e51a83bc5d0663911bbec059ebf38749c Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Thu, 8 Apr 2021 19:53:32 +0700
Subject: [PATCH 06/17] Simpler test for I18n namespace conflict
---
test/mock_helpers/application_helper.rb | 8 --------
test/mock_helpers/view.rb | 4 ++++
test/pagy/extras/i18n_test.rb | 8 +++-----
3 files changed, 7 insertions(+), 13 deletions(-)
delete mode 100644 test/mock_helpers/application_helper.rb
diff --git a/test/mock_helpers/application_helper.rb b/test/mock_helpers/application_helper.rb
deleted file mode 100644
index b742b8505..000000000
--- a/test/mock_helpers/application_helper.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-module ApplicationHelper
- include Pagy::Frontend
-
- def any_method_name()
- I18n.t("test")
- end
-
-end
\ No newline at end of file
diff --git a/test/mock_helpers/view.rb b/test/mock_helpers/view.rb
index e7d0fa897..6909d7ad0 100644
--- a/test/mock_helpers/view.rb
+++ b/test/mock_helpers/view.rb
@@ -8,6 +8,10 @@ def initialize(url='http://example.com:3000/foo?page=2')
@url = url
end
+ def test_i18n_call
+ I18n.t('test')
+ end
+
def request
Rack::Request.new(Rack::MockRequest.env_for(@url))
end
diff --git a/test/pagy/extras/i18n_test.rb b/test/pagy/extras/i18n_test.rb
index 4975a362d..33766bd73 100644
--- a/test/pagy/extras/i18n_test.rb
+++ b/test/pagy/extras/i18n_test.rb
@@ -7,16 +7,14 @@
SimpleCov.command_name 'i18n' if ENV['RUN_SIMPLECOV'] == 'true'
-require_relative '../../mock_helpers/application_helper'
-include ApplicationHelper
-
describe Pagy::Frontend do
let(:view) { MockView.new }
describe "#pagy_t with I18n" do
- it 'works with an included Module' do
- ApplicationHelper.any_method_name()
+
+ it 'does not conflict with the I18n gem namespace' do
+ view.test_i18n_call
end
it 'pluralizes' do
From aac54aad8a6a0cc338f65ce07f19dd61132790f5 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Thu, 8 Apr 2021 15:58:02 +0700
Subject: [PATCH 07/17] Renaming prepended modules with more specific and safe
naming convention (see Issue #290 PR #293)
---
lib/pagy/extras/elasticsearch_rails.rb | 2 +-
lib/pagy/extras/items.rb | 8 ++++----
lib/pagy/extras/overflow.rb | 8 ++++----
lib/pagy/extras/searchkick.rb | 2 +-
lib/pagy/extras/shared.rb | 4 ++--
lib/pagy/extras/trim.rb | 4 ++--
6 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/lib/pagy/extras/elasticsearch_rails.rb b/lib/pagy/extras/elasticsearch_rails.rb
index f43eb7725..a16b03ffc 100644
--- a/lib/pagy/extras/elasticsearch_rails.rb
+++ b/lib/pagy/extras/elasticsearch_rails.rb
@@ -41,7 +41,7 @@ def pagy_elasticsearch_rails(pagy_search_args, vars={})
vars[:count] = total.is_a?(Hash) ? total['value'] : total
pagy = Pagy.new(vars)
# with :last_page overflow we need to re-run the method in order to get the hits
- if defined?(Pagy::Overflow) && pagy.overflow? && pagy.vars[:overflow] == :last_page
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page))
end
return pagy, called.empty? ? response : response.send(*called)
diff --git a/lib/pagy/extras/items.rb b/lib/pagy/extras/items.rb
index 646e627b9..75181696e 100644
--- a/lib/pagy/extras/items.rb
+++ b/lib/pagy/extras/items.rb
@@ -12,7 +12,7 @@ class Pagy
ITEMS_PLACEHOLDER = '__pagy_items__'
- module Items ; private
+ module UseItemsExtra ; private
[:pagy_get_vars, :pagy_countless_get_vars, :pagy_elasticsearch_rails_get_vars, :pagy_searchkick_get_vars].each do |meth|
if Backend.private_method_defined?(meth, true)
@@ -25,12 +25,12 @@ module Items ; private
end
end
- Backend.prepend Items
+ Backend.prepend UseItemsExtra
module Frontend
- module Items
+ module UseItemsExtra
def pagy_url_for(page, pagy, url=false)
p_vars = pagy.vars
params = request.GET.merge(p_vars[:params])
@@ -39,7 +39,7 @@ def pagy_url_for(page, pagy, url=false)
"#{request.base_url if url}#{request.path}?#{Rack::Utils.build_nested_query(pagy_get_params(params))}#{p_vars[:anchor]}"
end
end
- prepend Items
+ prepend UseItemsExtra
# Return the items selector HTML. For example "Show [20] items per page"
def pagy_items_selector_js(pagy, id=pagy_id)
diff --git a/lib/pagy/extras/overflow.rb b/lib/pagy/extras/overflow.rb
index 3afbcf798..5fd7e147c 100644
--- a/lib/pagy/extras/overflow.rb
+++ b/lib/pagy/extras/overflow.rb
@@ -4,7 +4,7 @@
class Pagy
- module Overflow
+ module UseOverflowExtra
VARS[:overflow] = :empty_page
def overflow? = @overflow
@@ -41,14 +41,14 @@ def series(size=@vars[:size])
end
end
- prepend Overflow
+ prepend UseOverflowExtra
# support for Pagy::Countless
if defined?(Pagy::Countless)
class Countless
- module Overflow
+ module UseOverflowExtra
def finalize(items)
@overflow = false
@@ -68,7 +68,7 @@ def finalize(items)
end
end
- prepend Overflow
+ prepend UseOverflowExtra
end
end
diff --git a/lib/pagy/extras/searchkick.rb b/lib/pagy/extras/searchkick.rb
index 11f04dbdf..77db7f6f2 100644
--- a/lib/pagy/extras/searchkick.rb
+++ b/lib/pagy/extras/searchkick.rb
@@ -39,7 +39,7 @@ def pagy_searchkick(pagy_search_args, vars={})
vars[:count] = results.total_count
pagy = Pagy.new(vars)
# with :last_page overflow we need to re-run the method in order to get the hits
- if defined?(Pagy::Overflow) && pagy.overflow? && pagy.vars[:overflow] == :last_page
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page))
end
return pagy, called.empty? ? results : results.send(*called)
diff --git a/lib/pagy/extras/shared.rb b/lib/pagy/extras/shared.rb
index 98172b948..a2edb1e91 100644
--- a/lib/pagy/extras/shared.rb
+++ b/lib/pagy/extras/shared.rb
@@ -30,14 +30,14 @@ module Frontend
if defined?(Oj)
# it returns a script tag with the JSON-serialized args generated with the faster oj gem
def pagy_json_tag(pagy, *args)
- args << ( defined?(Trim) && pagy.vars[:page_param] )
+ args << ( defined?(UseTrimExtra) && pagy.vars[:page_param] )
%()
end
else
require 'json'
# it returns a script tag with the JSON-serialized args generated with the slower to_json
def pagy_json_tag(pagy, *args)
- args << ( defined?(Trim) && pagy.vars[:page_param] )
+ args << ( defined?(UseTrimExtra) && pagy.vars[:page_param] )
%()
end
end
diff --git a/lib/pagy/extras/trim.rb b/lib/pagy/extras/trim.rb
index be97050ff..b5e92473d 100644
--- a/lib/pagy/extras/trim.rb
+++ b/lib/pagy/extras/trim.rb
@@ -4,7 +4,7 @@
class Pagy
- module Trim
+ module UseTrimExtra
def pagy_link_proc(pagy, link_extra='')
link_proc = super(pagy, link_extra)
re = /[?&]#{pagy.vars[:page_param]}=1\b(?!&)|\b#{pagy.vars[:page_param]}=1&/
@@ -14,6 +14,6 @@ def pagy_link_proc(pagy, link_extra='')
end
end
end
- Frontend.prepend Trim
+ Frontend.prepend UseTrimExtra
end
From b6387648450c3d3b018691b944c48d33ae58a30e Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Thu, 8 Apr 2021 20:09:39 +0700
Subject: [PATCH 08/17] code-restyling: root files and Pagy Core
---
.rubocop.yml | 26 ++++++++++++----
Gemfile | 12 +++-----
Rakefile | 1 -
lib/pagy.rb | 70 ++++++++++++++++++++++++++----------------
lib/pagy/backend.rb | 7 +++--
lib/pagy/countless.rb | 18 ++++++-----
lib/pagy/exceptions.rb | 8 +++--
lib/pagy/frontend.rb | 66 ++++++++++++++++++++++++++-------------
8 files changed, 133 insertions(+), 75 deletions(-)
diff --git a/.rubocop.yml b/.rubocop.yml
index 1d033bad8..b66f74d19 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -3,24 +3,38 @@ require:
- rubocop-rake
- rubocop-minitest
+# trying to be good O:)
AllCops:
TargetRubyVersion: 3.0
NewCops: enable
+# No, thank you!
Layout:
Enabled: false
+# affect performance
Metrics:
Enabled: false
-Style:
+# not cool
+Style/CommentedKeyword:
Enabled: false
-
-Bundler/OrderedGems:
+Style/EmptyCaseCondition:
+ Enabled: false
+Style/Documentation:
Enabled: false
-Lint/RaiseException:
+# these cops are disabled only in the test files in order to
+# allow to copy and paste the failed output for test reconciliation
+Style/StringLiterals:
Enabled: true
-
-Lint/StructNewOverride:
+ Exclude:
+ - test/**/*
+Style/HashSyntax:
+ Enabled: true
+ Exclude:
+ - test/**/*
+Style/SymbolArray:
Enabled: true
+ Exclude:
+ - test/**/*
diff --git a/Gemfile b/Gemfile
index eec1827e3..4288f25b6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,23 +2,22 @@ source "https://rubygems.org"
gemspec
-gem 'rake'
-gem 'rack'
gem 'i18n'
-
gem 'oj', require: false # false is for testing with or without it
+gem 'rack'
+gem 'rake'
gem 'puma'
group :test do
+ gem 'codecov', require: false
+ gem 'minitest'
+ gem 'minitest-reporters'
gem 'rubocop', '~> 1.11', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rake', require: false
gem 'rubocop-minitest', require: false
gem 'simplecov', require: false
- gem 'codecov', require: false
- gem 'minitest'
- gem 'minitest-reporters'
end
group :apps do
@@ -29,7 +28,6 @@ group :apps do
end
group :performance do
- #benchmark/profiling
gem 'benchmark-ips'
gem 'kalibera'
gem 'memory_profiler'
diff --git a/Rakefile b/Rakefile
index 8a3348e11..0bad66eb2 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,3 @@
-# encoding: utf-8
# frozen_string_literal: true
require "bundler/setup"
diff --git a/lib/pagy.rb b/lib/pagy.rb
index 95ed36226..6084658a9 100644
--- a/lib/pagy.rb
+++ b/lib/pagy.rb
@@ -1,48 +1,66 @@
# See Pagy API documentation: https://ddnexus.github.io/pagy/api/pagy
-# encoding: utf-8
# frozen_string_literal: true
require 'pathname'
-class Pagy ; VERSION = '4.1.0'
+# main class
+class Pagy
+ VERSION = '4.1.0'
# Root pathname to get the path of Pagy files like templates or dictionaries
- def self.root = @root ||= Pathname.new(__FILE__).dirname.freeze
+ def self.root
+ @root ||= Pathname.new(__dir__).freeze
+ end
# default vars
- VARS = { page:1, items:20, outset:0, size:[1,4,4,1], page_param: :page, params:{}, anchor:'', link_extra:'', i18n_key:'pagy.item_name', cycle:false }
+ VARS = { page: 1, items: 20, outset: 0, size: [1, 4, 4, 1], page_param: :page, # rubocop:disable Style/MutableConstant
+ params: {}, anchor: '', link_extra: '', i18n_key: 'pagy.item_name', cycle: false }
attr_reader :count, :page, :items, :vars, :pages, :last, :offset, :from, :to, :prev, :next
+ INSTANCE_VARS_MIN = { count: 0, items: 1, page: 1, outset: 0 }.freeze
+
# Merge and validate the options, do some simple arithmetic and set the instance variables
def initialize(vars)
- @vars = VARS.merge(vars.delete_if{|_,v| v.nil? || v == '' }) # default vars + cleaned vars
- { count:0, items:1, outset:0, page:1 }.each do |k,min| # validate instance variables
- (@vars[k] && instance_variable_set(:"@#{k}", @vars[k].to_i) >= min) \
- or raise(VariableError.new(self), "expected :#{k} >= #{min}; got #{@vars[k].inspect}")
+ @vars = VARS.merge( vars.delete_if{|_,v| v.nil? || v == '' } )
+
+ INSTANCE_VARS_MIN.each do |name,min|
+ raise VariableError.new(self), "expected :#{name} >= #{min}; got #{@vars[name].inspect}" \
+ unless @vars[name] && instance_variable_set(:"@#{name}", @vars[name].to_i) >= min
end
- @pages = @last = [(@count.to_f / @items).ceil, 1].max # cardinal and ordinal meanings
- @page <= @last or raise(OverflowError.new(self), "expected :page in 1..#{@last}; got #{@page.inspect}")
- @offset = @items * (@page - 1) + @outset # pagination offset + outset (initial offset)
- @items = @count - ((@pages-1) * @items) if @page == @last && @count > 0 # adjust items for last non-empty page
- @from = @count == 0 ? 0 : @offset + 1 - @outset # page begins from item
- @to = @count == 0 ? 0 : @offset + @items - @outset # page ends to item
- @prev = (@page-1 unless @page == 1) # nil if no prev page
- @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1 # nil if no next page, 1 if :cycle
+ @pages = @last = [(@count.to_f / @items).ceil, 1].max
+ raise OverflowError.new(self), "expected :page in 1..#{@last}; got #{@page.inspect}" if @page > @last
+
+ @offset = @items * (@page - 1) + @outset
+ @items = @count - ((@pages-1) * @items) if @page == @last && @count.positive?
+ @from = @count.zero? ? 0 : @offset + 1 - @outset
+ @to = @count.zero? ? 0 : @offset + @items - @outset
+ @prev = (@page-1 unless @page == 1)
+ @next = @page == @last ? (1 if @vars[:cycle]) : @page + 1
end
# Return the array of page numbers and :gap items e.g. [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
def series(size=@vars[:size])
- (series = []) and size.empty? and return series
- 4.times{|i| (size[i]>=0 rescue nil) or raise(VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}")}
- [*0..size[0], *@page-size[1]..@page+size[2], *@last-size[3]+1..@last+1].sort!.each_cons(2) do |a, b|
- if a<0 || a==b || a>@last; next # skip out of range and duplicates
- elsif a+1 == b; series.push(a) # no gap -> no additions
- elsif a+2 == b; series.push(a, a+1) # 1 page gap -> fill with missing page
- else series.push(a, :gap) # n page gap -> add gap
- end # skip the end boundary (last+1)
- end # shift the start boundary (0) and
- series.shift; series[series.index(@page)] = @page.to_s; series # convert the current page to String
+ return [] if size.empty?
+ raise VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}" \
+ unless size.size == 4 && size.all?{ |num| num >= 0 rescue false } # rubocop:disable Style/RescueModifier
+
+ [].tap do |series|
+ [ *0..size[0], # initial pages from 0
+ *@page-size[1]..@page+size[2], # around current page
+ *@last-size[3]+1..@last+1 # final pages till @last+1
+ ].sort!.each_cons(2) do |left, right| # sort and loop by 2
+ next if left.negative? || left == right # skip out of range and duplicates
+ break if left > @last # break if out of @last boundary
+ case right
+ when left+1 then series.push(left) # no gap -> no additions
+ when left+2 then series.push(left, left+1) # 1 page gap -> fill with missing page
+ else series.push(left, :gap) # n page gap -> add gap
+ end
+ end
+ series.shift # shift the start boundary (0)
+ series[series.index(@page)] = @page.to_s # convert the current page to String
+ end
end
end
diff --git a/lib/pagy/backend.rb b/lib/pagy/backend.rb
index 925e67a31..5c094071b 100644
--- a/lib/pagy/backend.rb
+++ b/lib/pagy/backend.rb
@@ -1,5 +1,4 @@
# See Pagy::Backend API documentation: https://ddnexus.github.io/pagy/api/backend
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
@@ -8,12 +7,14 @@ class Pagy
# See also the extras if you need specialized methods to paginate Arrays or other collections
- module Backend ; private # the whole module is private so no problem with including it in a controller
+
+ module Backend
+ private # the whole module is private so no problem with including it in a controller
# Return Pagy object and items
def pagy(collection, vars={})
pagy = Pagy.new(pagy_get_vars(collection, vars))
- return pagy, pagy_get_items(collection, pagy)
+ [ pagy, pagy_get_items(collection, pagy) ]
end
# Sub-method called only by #pagy: here for easy customization of variables by overriding
diff --git a/lib/pagy/countless.rb b/lib/pagy/countless.rb
index 69d9f02f8..fa7277bfc 100644
--- a/lib/pagy/countless.rb
+++ b/lib/pagy/countless.rb
@@ -1,4 +1,3 @@
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy'
@@ -7,23 +6,26 @@ class Pagy
class Countless < Pagy
+ INSTANCE_VARS_MIN = { items: 1, page: 1, outset: 0 }.freeze
+
# Merge and validate the options, do some simple arithmetic and set a few instance variables
def initialize(vars={}) # rubocop:disable Lint/MissingSuper
@vars = VARS.merge(vars.delete_if{|_,v| v.nil? || v == '' }) # default vars + cleaned vars (can be overridden)
- { items:1, outset:0, page:1 }.each do |k,min| # validate instance variables
- (@vars[k] && instance_variable_set(:"@#{k}", @vars[k].to_i) >= min) \
- or raise(VariableError.new(self), "expected :#{k} >= #{min}; got #{@vars[k].inspect}")
+ INSTANCE_VARS_MIN.each do |k,min| # validate instance variables
+ raise VariableError.new(self), "expected :#{k} >= #{min}; got #{@vars[k].inspect}" \
+ unless @vars[k] && instance_variable_set(:"@#{k}", @vars[k].to_i) >= min
end
@offset = @items * (@page - 1) + @outset # pagination offset + outset (initial offset)
end
# Finalize the instance variables based on the fetched items
def finalize(fetched)
- fetched == 0 && @page > 1 and raise(OverflowError.new(self), "page #{@page} got no items")
+ raise OverflowError.new(self), "page #{@page} got no items" \
+ if fetched.zero? && @page > 1
@pages = @last = (fetched > @items ? @page + 1 : @page) # set the @pages and @last
- @items = fetched if fetched < @items && fetched > 0 # adjust items for last non-empty page
- @from = fetched == 0 ? 0 : @offset + 1 - @outset # page begins from item
- @to = fetched == 0 ? 0 : @offset + @items - @outset # page ends to item
+ @items = fetched if fetched < @items && fetched.positive? # adjust items for last non-empty page
+ @from = fetched.zero? ? 0 : @offset + 1 - @outset # page begins from item
+ @to = fetched.zero? ? 0 : @offset + @items - @outset # page ends to item
@prev = (@page-1 unless @page == 1) # nil if no prev page
@next = @page == @last ? (1 if @vars[:cycle]) : @page + 1 # nil if no next page, 1 if :cycle
self
diff --git a/lib/pagy/exceptions.rb b/lib/pagy/exceptions.rb
index ebfb88c38..8c8fa417c 100644
--- a/lib/pagy/exceptions.rb
+++ b/lib/pagy/exceptions.rb
@@ -1,5 +1,8 @@
+# frozen_string_literal: true
+
class Pagy
+ # generic variable error
class VariableError < ArgumentError
attr_reader :pagy
@@ -9,13 +12,14 @@ def initialize(pagy)
end
def variable
- message =~ /expected :([\w]+)/
- $1.to_sym if $1
+ message =~ /expected :(\w+)/
+ Regexp.last_match(1)&.to_sym
end
def value = pagy.vars[variable]
end
+ # specific overflow error
class OverflowError < VariableError; end
end
diff --git a/lib/pagy/frontend.rb b/lib/pagy/frontend.rb
index f61554784..3e1c418ce 100644
--- a/lib/pagy/frontend.rb
+++ b/lib/pagy/frontend.rb
@@ -1,5 +1,4 @@
# See Pagy::Frontend API documentation: https://ddnexus.github.io/pagy/api/frontend
-# encoding: utf-8
# frozen_string_literal: true
require 'yaml'
@@ -10,11 +9,11 @@ class Pagy
# I18n static hash loaded at startup, used as default alternative to the i18n gem.
# see https://ddnexus.github.io/pagy/api/frontend#i18n
- I18n = eval(Pagy.root.join('locales', 'utils', 'i18n.rb').read) #rubocop:disable Security/Eval
+ I18n = eval Pagy.root.join('locales', 'utils', 'i18n.rb').read #rubocop:disable Security/Eval
module Helpers
# This works with all Rack-based frameworks (Sinatra, Padrino, Rails, ...)
- def pagy_url_for(page, pagy, url=false)
+ def pagy_url_for(page, pagy, url=nil)
p_vars = pagy.vars
params = request.GET.merge(p_vars[:params])
params[p_vars[:page_param].to_s] = page
@@ -33,42 +32,65 @@ module Frontend
# Generic pagination: it returns the html with the series of links to the pages
def pagy_nav(pagy)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
-
- html = (p_prev ? %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} )
- : %(#{pagy_t('pagy.nav.prev')} ))
+ link = pagy_link_proc(pagy)
+ p_prev = pagy.prev
+ p_next = pagy.next
+ html = if p_prev
+ %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} )
+ else
+ %(#{pagy_t('pagy.nav.prev')} )
+ end
pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
- html << if item.is_a?(Integer); %(#{link.call item} ) # page link
- elsif item.is_a?(String) ; %(#{item} ) # current page
- elsif item == :gap ; %(#{pagy_t('pagy.nav.gap')} ) # page gap
+ html << case item
+ when Integer then %(#{link.call item} ) # page link
+ when String then %(#{item} ) # current page
+ when :gap then %(#{pagy_t('pagy.nav.gap')} ) # page gap
end
end
- html << (p_next ? %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'})
- : %(#{pagy_t('pagy.nav.next')}))
+ html << if p_next
+ %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'})
+ else
+ %(#{pagy_t('pagy.nav.next')})
+ end
%()
end
# Return examples: "Displaying items 41-60 of 324 in total" of "Displaying Products 41-60 of 324 in total"
def pagy_info(pagy, item_name=nil)
- key = if (count = pagy.count) == 0 ; 'pagy.info.no_items'
- else pagy.pages == 1 ? 'pagy.info.single_page' : 'pagy.info.multiple_pages'
- end
- pagy_t(key, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count), count: count, from: pagy.from, to: pagy.to)
+ count = pagy.count
+ key = if count.zero?
+ 'pagy.info.no_items'
+ elsif pagy.pages == 1
+ 'pagy.info.single_page'
+ else
+ 'pagy.info.multiple_pages'
+ end
+ pagy_t key, item_name: item_name || pagy_t(pagy.vars[:i18n_key], count: count),
+ count: count,
+ from: pagy.from,
+ to: pagy.to
end
# Returns a performance optimized proc to generate the HTML links
# Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
def pagy_link_proc(pagy, link_extra='')
- p_prev, p_next = pagy.prev, pagy.next
- a, b = %(#{text}"}
+ p_prev = pagy.prev
+ p_next = pagy.next
+ left, right = %(#{text}"
+ end
end
# Similar to I18n.t: just ~18x faster using ~10x less memory
# (@pagy_locale explicitly initilized in order to avoid warning)
- def pagy_t(key, **opts) = Pagy::I18n.t(@pagy_locale||=nil, key, **opts)
+ def pagy_t(key, **opts)
+ Pagy::I18n.t @pagy_locale||=nil, key, **opts
+ end
end
end
From b2dc35aeaba217f5b65e24900c4f9a5f60472105 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Thu, 8 Apr 2021 20:11:46 +0700
Subject: [PATCH 09/17] code-restyling: locales, config
---
lib/config/pagy.rb | 1 -
lib/locales/utils/i18n.rb | 1 -
lib/locales/utils/loader.rb | 12 +++++-----
lib/locales/utils/p11n.rb | 44 ++++++++++++++++++++-----------------
4 files changed, 31 insertions(+), 27 deletions(-)
diff --git a/lib/config/pagy.rb b/lib/config/pagy.rb
index f6865b37a..c76139539 100644
--- a/lib/config/pagy.rb
+++ b/lib/config/pagy.rb
@@ -1,4 +1,3 @@
-# encoding: utf-8
# frozen_string_literal: true
# Pagy initializer file (4.1.0)
diff --git a/lib/locales/utils/i18n.rb b/lib/locales/utils/i18n.rb
index 4dcc5c91d..ce93da5e0 100644
--- a/lib/locales/utils/i18n.rb
+++ b/lib/locales/utils/i18n.rb
@@ -1,5 +1,4 @@
# See https://ddnexus.github.io/pagy/api/frontend#i18n
-# encoding: utf-8
# frozen_string_literal: true
# this file returns the I18n hash used as default alternative to the i18n gem
diff --git a/lib/locales/utils/loader.rb b/lib/locales/utils/loader.rb
index 942dfb827..c6812875f 100644
--- a/lib/locales/utils/loader.rb
+++ b/lib/locales/utils/loader.rb
@@ -1,18 +1,20 @@
-# encoding: utf-8
# frozen_string_literal: true
# the whole file will be eval'ed/executed and gc-collected after returning/executing the loader proc
# eval: no need for the whole file in memory
-plurals, _ = eval(Pagy.root.join('locales', 'utils', 'p11n.rb').read) #rubocop:disable Security/Eval
+plurals, = eval Pagy.root.join('locales', 'utils', 'p11n.rb').read # rubocop:disable Security/Eval
# flatten the dictionary file nested keys
# convert each value to a simple ruby interpolation proc
flatten = lambda do |hash, key=''|
hash.each.reduce({}) do |h, (k, v)|
- v.is_a?(Hash) \
- ? h.merge!(flatten.call(v, "#{key}#{k}."))
- : h.merge!(eval %({"#{key}#{k}" => lambda{|vars|"#{v.gsub(/%{[^}]+?}/){|m| "\#{vars[:#{m[2..-2]}]||'#{m}'}" }}"}})) #rubocop:disable Security/Eval
+ if v.is_a?(Hash)
+ h.merge! flatten.call(v, "#{key}#{k}.")
+ else
+ code = %({"#{key}#{k}" => lambda{|vars|"#{v.gsub(/%{[^}]+?}/){|m| "\#{vars[:#{m[2..-2]}]||'#{m}'}" }}"}})
+ h.merge! eval(code) # rubocop:disable Security/Eval
+ end
end
end
diff --git a/lib/locales/utils/p11n.rb b/lib/locales/utils/p11n.rb
index bad7a2368..9685af75c 100644
--- a/lib/locales/utils/p11n.rb
+++ b/lib/locales/utils/p11n.rb
@@ -1,5 +1,4 @@
# See https://ddnexus.github.io/pagy/api/frontend#i18n
-# encoding: utf-8
# frozen_string_literal: true
# This file adds support for multiple built-in plualization types.
@@ -18,46 +17,51 @@
# Each proc may apply to one or more locales below.
# Pluralization logic adapted from https://github.com/svenfuchs/rails-i18n
p11n = {
- one_other: lambda {|n| n == 1 ? 'one' : 'other'}, # default
+ one_other: -> (n){ n == 1 ? 'one' : 'other' }, # default
east_slavic: lambda do |n|
n ||= 0
mod10 = n % 10
mod100 = n % 100
- if mod10 == 1 && mod100 != 11 ; 'one'
- elsif from2to4.include?(mod10) && !from12to14.include?(mod100) ; 'few'
- elsif mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) ; 'many'
- else 'other'
+ case
+ when mod10 == 1 && mod100 != 11 then 'one'
+ when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
+ when mod10 == 0 || from5to9.include?(mod10) || from11to14.include?(mod100) then 'many' # rubocop:disable Style/NumericPredicate
+ else 'other'
end
end,
west_slavic: lambda do |n|
- if n == 1 ; 'one'
- elsif [2, 3, 4].include?(n) ; 'few'
- else ; 'other'
- end
+ case n
+ when 1 then 'one'
+ when 2, 3, 4 then 'few'
+ else 'other'
+ end
end,
one_two_other: lambda do |n|
- if n == 1 ; 'one'
- elsif n == 2 ; 'two'
- else 'other'
+ case n
+ when 1 then 'one'
+ when 2 then 'two'
+ else 'other'
end
end,
- one_upto_two_other: lambda {|n| n && n >= 0 && n < 2 ? 'one' : 'other'},
+ one_upto_two_other: -> (n){ n && n >= 0 && n < 2 ? 'one' : 'other' },
- other: Proc.new { 'other' },
+ other: -> (*){ 'other' },
polish: lambda do |n|
n ||= 0
- mod10 = n % 10
+ mod10 = n % 10
mod100 = n % 100
- if n == 1 ; 'one'
- elsif from2to4.include?(mod10) && !from12to14.include?(mod100) ; 'few'
- elsif (from0to1 + from5to9).include?(mod10) || from12to14.include?(mod100) ; 'many'
- else 'other'
+
+ case
+ when n == 1 then 'one'
+ when from2to4.include?(mod10) && !from12to14.include?(mod100) then 'few'
+ when (from0to1 + from5to9).include?(mod10) || from12to14.include?(mod100) then 'many'
+ else 'other'
end
end
}
From cb673530eca0916771d9f4eebe56899f9eac9ad8 Mon Sep 17 00:00:00 2001
From: Domizio Demichelis
Date: Thu, 8 Apr 2021 20:13:10 +0700
Subject: [PATCH 10/17] code-restyling: extras
---
lib/pagy.rb | 28 ++++-----
lib/pagy/countless.rb | 1 +
lib/pagy/extras/arel.rb | 6 +-
lib/pagy/extras/array.rb | 6 +-
lib/pagy/extras/bootstrap.rb | 81 ++++++++++++++++--------
lib/pagy/extras/bulma.rb | 86 +++++++++++++++----------
lib/pagy/extras/countless.rb | 9 +--
lib/pagy/extras/elasticsearch_rails.rb | 13 ++--
lib/pagy/extras/foundation.rb | 81 +++++++++++++++---------
lib/pagy/extras/headers.rb | 22 ++++---
lib/pagy/extras/i18n.rb | 7 ++-
lib/pagy/extras/items.rb | 29 +++++----
lib/pagy/extras/materialize.rb | 80 ++++++++++++++---------
lib/pagy/extras/metadata.rb | 45 +++++++------
lib/pagy/extras/navs.rb | 55 +++++++++++-----
lib/pagy/extras/overflow.rb | 13 ++--
lib/pagy/extras/searchkick.rb | 15 ++---
lib/pagy/extras/semantic.rb | 75 ++++++++++++++--------
lib/pagy/extras/shared.rb | 18 +++---
lib/pagy/extras/support.rb | 15 +++--
lib/pagy/extras/trim.rb | 14 +++--
lib/pagy/extras/uikit.rb | 87 +++++++++++++++++---------
lib/pagy/frontend.rb | 23 ++++---
test/pagy/extras/semantic_test.rb | 1 +
24 files changed, 499 insertions(+), 311 deletions(-)
diff --git a/lib/pagy.rb b/lib/pagy.rb
index 6084658a9..5c7d79b0d 100644
--- a/lib/pagy.rb
+++ b/lib/pagy.rb
@@ -45,22 +45,22 @@ def series(size=@vars[:size])
raise VariableError.new(self), "expected 4 items >= 0 in :size; got #{size.inspect}" \
unless size.size == 4 && size.all?{ |num| num >= 0 rescue false } # rubocop:disable Style/RescueModifier
- [].tap do |series|
- [ *0..size[0], # initial pages from 0
- *@page-size[1]..@page+size[2], # around current page
- *@last-size[3]+1..@last+1 # final pages till @last+1
- ].sort!.each_cons(2) do |left, right| # sort and loop by 2
- next if left.negative? || left == right # skip out of range and duplicates
- break if left > @last # break if out of @last boundary
- case right
- when left+1 then series.push(left) # no gap -> no additions
- when left+2 then series.push(left, left+1) # 1 page gap -> fill with missing page
- else series.push(left, :gap) # n page gap -> add gap
- end
+ series = []
+ [ *0..size[0], # initial pages from 0
+ *@page-size[1]..@page+size[2], # around current page
+ *@last-size[3]+1..@last+1 # final pages till @last+1
+ ].sort!.each_cons(2) do |left, right| # sort and loop by 2
+ next if left.negative? || left == right # skip out of range and duplicates
+ break if left > @last # break if out of @last boundary
+ case right
+ when left+1 then series.push(left) # no gap -> no additions
+ when left+2 then series.push(left, left+1) # 1 page gap -> fill with missing page
+ else series.push(left, :gap) # n page gap -> add gap
end
- series.shift # shift the start boundary (0)
- series[series.index(@page)] = @page.to_s # convert the current page to String
end
+ series.shift # shift the start boundary (0)
+ series[series.index(@page)] = @page.to_s # convert the current page to String
+ series
end
end
diff --git a/lib/pagy/countless.rb b/lib/pagy/countless.rb
index fa7277bfc..3ea12c46d 100644
--- a/lib/pagy/countless.rb
+++ b/lib/pagy/countless.rb
@@ -22,6 +22,7 @@ def initialize(vars={}) # rubocop:disable Lint/MissingSuper
def finalize(fetched)
raise OverflowError.new(self), "page #{@page} got no items" \
if fetched.zero? && @page > 1
+
@pages = @last = (fetched > @items ? @page + 1 : @page) # set the @pages and @last
@items = fetched if fetched < @items && fetched.positive? # adjust items for last non-empty page
@from = fetched.zero? ? 0 : @offset + 1 - @outset # page begins from item
diff --git a/lib/pagy/extras/arel.rb b/lib/pagy/extras/arel.rb
index 3e6dfaef9..b92fd2233 100644
--- a/lib/pagy/extras/arel.rb
+++ b/lib/pagy/extras/arel.rb
@@ -1,13 +1,13 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/arel
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
- module Backend ; private
+ module Backend
+ private
def pagy_arel(collection, vars={})
pagy = Pagy.new(pagy_arel_get_vars(collection, vars))
- return pagy, pagy_get_items(collection, pagy)
+ [ pagy, pagy_get_items(collection, pagy) ]
end
def pagy_arel_get_vars(collection, vars)
diff --git a/lib/pagy/extras/array.rb b/lib/pagy/extras/array.rb
index 35870cb93..3dc08621d 100644
--- a/lib/pagy/extras/array.rb
+++ b/lib/pagy/extras/array.rb
@@ -1,15 +1,15 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/array
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
# Add specialized backend methods to paginate array collections
- module Backend ; private
+ module Backend
+ private
# Return Pagy object and items
def pagy_array(array, vars={})
pagy = Pagy.new(pagy_array_get_vars(array, vars))
- return pagy, array[pagy.offset, pagy.items]
+ [ pagy, array[pagy.offset, pagy.items] ]
end
# Sub-method called only by #pagy_array: here for easy customization of variables by overriding
diff --git a/lib/pagy/extras/bootstrap.rb b/lib/pagy/extras/bootstrap.rb
index d5c3b8da8..89a008414 100644
--- a/lib/pagy/extras/bootstrap.rb
+++ b/lib/pagy/extras/bootstrap.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/bootstrap
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy/extras/shared'
@@ -9,47 +8,75 @@ module Frontend
# Pagination for bootstrap: it returns the html with the series of links to the pages
def pagy_bootstrap_nav(pagy)
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next
+ link = pagy_link_proc(pagy, 'class="page-link"')
- html = (p_prev ? %(
))
+ html = +%()
end
# Javascript pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_bootstrap_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="page-link"'), pagy.prev, pagy.next
- tags = { 'before' => p_prev ? %(
) }
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination for bootstrap: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_bootstrap_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %() + %(
' }
- %(#{pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)})
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination for Bulma: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_bulma_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %() \
- + %(
#{
+ pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))
+ })
end
+ private
+
+ def pagy_bulma_prev_next_html(pagy, link)
+ html = if (p_prev = pagy.prev)
+ link.call p_prev, pagy_t('pagy.nav.prev'), 'class="pagination-previous" aria-label="previous page"'
+ else
+ %(#{pagy_t 'pagy.nav.prev'})
+ end
+ html << if (p_next = pagy.next)
+ link.call p_next, pagy_t('pagy.nav.next'), 'class="pagination-next" aria-label="next page"'
+ else
+ %(#{pagy_t 'pagy.nav.next' })
+ end
+ end
+
end
end
diff --git a/lib/pagy/extras/countless.rb b/lib/pagy/extras/countless.rb
index 2b50ec9d4..d7bbdd33b 100644
--- a/lib/pagy/extras/countless.rb
+++ b/lib/pagy/extras/countless.rb
@@ -1,17 +1,17 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/countless
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy/countless'
class Pagy
- module Backend ; private # the whole module is private so no problem with including it in a controller
+ module Backend
+ private # the whole module is private so no problem with including it in a controller
# Return Pagy object and items
def pagy_countless(collection, vars={})
pagy = Pagy::Countless.new(pagy_countless_get_vars(collection, vars))
- return pagy, pagy_countless_get_items(collection, pagy)
+ [ pagy, pagy_countless_get_items(collection, pagy) ]
end
# Sub-method called only by #pagy_countless: here for easy customization of variables by overriding
@@ -26,7 +26,8 @@ def pagy_countless_get_items(collection, pagy)
items = collection.offset(pagy.offset).limit(pagy.items + 1).to_a
items_size = items.size
items.pop if items_size == pagy.items + 1
- pagy.finalize(items_size) # finalize may adjust pagy.items, so must be used after checking the size
+ # finalize may adjust pagy.items, so must be used after checking the size
+ pagy.finalize(items_size)
items
end
diff --git a/lib/pagy/extras/elasticsearch_rails.rb b/lib/pagy/extras/elasticsearch_rails.rb
index a16b03ffc..f3121df59 100644
--- a/lib/pagy/extras/elasticsearch_rails.rb
+++ b/lib/pagy/extras/elasticsearch_rails.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/elasticsearch_rails
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
@@ -28,7 +27,8 @@ def self.new_from_elasticsearch_rails(response, vars={})
end
# Add specialized backend methods to paginate ElasticsearchRails searches
- module Backend ; private
+ module Backend
+ private
# Return Pagy object and items
def pagy_elasticsearch_rails(pagy_search_args, vars={})
@@ -39,12 +39,13 @@ def pagy_elasticsearch_rails(pagy_search_args, vars={})
response = model.search(query_or_payload, **options)
total = response.respond_to?(:raw_response) ? response.raw_response['hits']['total'] : response.response['hits']['total']
vars[:count] = total.is_a?(Hash) ? total['value'] : total
+
pagy = Pagy.new(vars)
# with :last_page overflow we need to re-run the method in order to get the hits
- if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
- return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page))
- end
- return pagy, called.empty? ? response : response.send(*called)
+ return pagy_elasticsearch_rails(pagy_search_args, vars.merge(page: pagy.page)) \
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
+
+ [ pagy, called.empty? ? response : response.send(*called) ]
end
# Sub-method called only by #pagy_elasticsearch_rails: here for easy customization of variables by overriding
diff --git a/lib/pagy/extras/foundation.rb b/lib/pagy/extras/foundation.rb
index dcefc3d09..e2b22c2dc 100644
--- a/lib/pagy/extras/foundation.rb
+++ b/lib/pagy/extras/foundation.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/foundation
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy/extras/shared'
@@ -9,49 +8,73 @@ module Frontend
# Pagination for Foundation: it returns the html with the series of links to the pages
def pagy_foundation_nav(pagy)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
+ link = pagy_link_proc(pagy)
- html = +(p_prev ? %(
)
+ html << pagy_foundation_next_html(pagy, link)
+ html << %(
)
end
# Javascript pagination for foundation: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_foundation_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
- tags = { 'before' => ( '
) }
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination for Foundation: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_foundation_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %() + %(
)
+ html << pagy_materialize_next_html(pagy, link)
+ html << %(
)
end
# Javascript pagination for materialize: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_materialize_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
- tags = { 'before' => ( '
) }
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_materialize_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %(
)
+ end
+ end
+
end
end
diff --git a/lib/pagy/extras/metadata.rb b/lib/pagy/extras/metadata.rb
index e6fce687d..fa189d86a 100644
--- a/lib/pagy/extras/metadata.rb
+++ b/lib/pagy/extras/metadata.rb
@@ -1,36 +1,41 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/metadata
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
# Add a specialized backend method for pagination metadata
- module Backend ; private
+ module Backend
+ private
- METADATA = [ :scaffold_url, :first_url, :prev_url, :page_url, :next_url, :last_url,
- :count, :page, :items, :vars, :pages, :last, :from, :to, :prev, :next, :series ]
- METADATA << :sequels if VARS.key?(:steps) # :steps gets defined along with the #sequels method
+ METADATA = %i[ scaffold_url first_url prev_url page_url next_url last_url
+ count page items vars pages last from to prev next series
+ ].tap do |metadata|
+ metadata << :sequels if VARS.key?(:steps) # :steps gets defined along with the #sequels method
+ end.freeze
VARS[:metadata] = METADATA.dup
include Helpers
- def pagy_metadata(pagy, url=false)
- names = pagy.vars[:metadata]
- (unknown = names - METADATA).empty? or raise(VariableError.new(pagy), "unknown metadata #{unknown.inspect}")
+ def pagy_metadata(pagy, url=nil)
+ names = pagy.vars[:metadata]
+ unknown = names - METADATA
+ raise VariableError.new(pagy), "unknown metadata #{unknown.inspect}" \
+ unless unknown.empty?
+
scaffold_url = pagy_url_for(PAGE_PLACEHOLDER, pagy, url)
- metadata = {}
- names.each do |key|
- metadata[key] = case key
- when :scaffold_url ; scaffold_url
- when :first_url ; scaffold_url.sub(PAGE_PLACEHOLDER, 1.to_s)
- when :prev_url ; scaffold_url.sub(PAGE_PLACEHOLDER, pagy.prev.to_s)
- when :page_url ; scaffold_url.sub(PAGE_PLACEHOLDER, pagy.page.to_s)
- when :next_url ; scaffold_url.sub(PAGE_PLACEHOLDER, pagy.next.to_s)
- when :last_url ; scaffold_url.sub(PAGE_PLACEHOLDER, pagy.last.to_s)
- else pagy.send(key)
- end
+ {}.tap do |metadata|
+ names.each do |key|
+ metadata[key] = case key
+ when :scaffold_url then scaffold_url
+ when :first_url then scaffold_url.sub(PAGE_PLACEHOLDER, 1.to_s)
+ when :prev_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.prev.to_s)
+ when :page_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.page.to_s)
+ when :next_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.next.to_s)
+ when :last_url then scaffold_url.sub(PAGE_PLACEHOLDER, pagy.last.to_s)
+ else pagy.send(key)
+ end
+ end
end
- metadata
end
end
diff --git a/lib/pagy/extras/navs.rb b/lib/pagy/extras/navs.rb
index 35c8612c7..35114ec66 100644
--- a/lib/pagy/extras/navs.rb
+++ b/lib/pagy/extras/navs.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/navs
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy/extras/shared'
@@ -9,30 +8,52 @@ module Frontend
# Javascript pagination: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
- tags = { 'before' => p_prev ? %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} )
- : %(#{pagy_t('pagy.nav.prev')} ),
+ link = pagy_link_proc(pagy)
+ tags = { 'before' => pagy_nav_prev_html(pagy, link),
'link' => %(#{link.call(PAGE_PLACEHOLDER)} ),
'active' => %(#{pagy.page} ),
'gap' => %(#{pagy_t('pagy.nav.gap')} ),
- 'after' => p_next ? %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'})
- : %(#{pagy_t('pagy.nav.next')}) }
- %(#{pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)})
+ 'after' => pagy_nav_next_html(pagy, link) }
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %()
- html << (p_prev ? %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} )
- : %(#{pagy_t('pagy.nav.prev')} ))
- input = %()
- html << %(#{pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)} )
- html << (p_next ? %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'})
- : %(#{pagy_t('pagy.nav.next')}))
- html << %(#{pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))})
+ link = pagy_link_proc(pagy)
+ p_page = pagy.page
+ p_pages = pagy.pages
+ input = %()
+
+ %(#{
+ pagy_nav_prev_html(pagy, link)
+ }#{
+ pagy_t('pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages)
+ } #{
+ pagy_nav_next_html(pagy, link)
+ }#{
+ pagy_json_tag(pagy, :combo_nav, id, p_page, pagy_marked_link(link))
+ })
end
+ private
+
+ def pagy_nav_prev_html(pagy, link)
+ if (p_prev = pagy.prev)
+ %(#{link.call p_prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"'} )
+ else
+ %(#{pagy_t('pagy.nav.prev')} )
+ end
+ end
+
+ def pagy_nav_next_html(pagy, link)
+ if (p_next = pagy.next)
+ %(#{link.call p_next, pagy_t('pagy.nav.next'), 'aria-label="next"'})
+ else
+ %(#{pagy_t('pagy.nav.next')})
+ end
+ end
+
end
end
diff --git a/lib/pagy/extras/overflow.rb b/lib/pagy/extras/overflow.rb
index 5fd7e147c..1ef571601 100644
--- a/lib/pagy/extras/overflow.rb
+++ b/lib/pagy/extras/overflow.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/overflow
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
@@ -34,8 +33,8 @@ module Series
def series(size=@vars[:size])
@page = @last # series for last page
super(size).tap do |s| # call original series
- s[s.index(@page.to_s)] = @page # string to integer (i.e. no current page)
- @page = @vars[:page] # restore the actual page
+ s[s.index(@page.to_s)] = @page # string to integer (i.e. no current page)
+ @page = @vars[:page] # restore the actual page
end
end
end
@@ -54,13 +53,13 @@ def finalize(items)
@overflow = false
super
rescue OverflowError
- @overflow = true # add the overflow flag
+ @overflow = true # add the overflow flag
case @vars[:overflow]
when :exception
- raise # same as without the extra
+ raise # same as without the extra
when :empty_page
- @offset = @items = @from = @to = 0 # vars relative to the actual page
- @vars[:size] = [] # no page in the series
+ @offset = @items = @from = @to = 0 # vars relative to the actual page
+ @vars[:size] = [] # no page in the series
self
else
raise VariableError.new(self), "expected :overflow variable in [:empty_page, :exception]; got #{@vars[:overflow].inspect}"
diff --git a/lib/pagy/extras/searchkick.rb b/lib/pagy/extras/searchkick.rb
index 77db7f6f2..a7558fadc 100644
--- a/lib/pagy/extras/searchkick.rb
+++ b/lib/pagy/extras/searchkick.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/searchkick
-# encoding: utf-8
# frozen_string_literal: true
class Pagy
@@ -10,7 +9,7 @@ module Searchkick
# returns an array used to delay the call of #search
# after the pagination variables are merged to the options
# it also pushes to the same array an eventually called method
- def pagy_searchkick(term = "*", **options, &block)
+ def pagy_searchkick(term = '*', **options, &block)
[self, term, options, block].tap do |args|
args.define_singleton_method(:method_missing){|*a| args += a}
end
@@ -27,7 +26,8 @@ def self.new_from_searchkick(results, vars={})
end
# Add specialized backend methods to paginate Searchkick::Results
- module Backend ; private
+ module Backend
+ private
# Return Pagy object and results
def pagy_searchkick(pagy_search_args, vars={})
@@ -37,12 +37,13 @@ def pagy_searchkick(pagy_search_args, vars={})
options[:page] = vars[:page]
results = model.search(term, **options, &block)
vars[:count] = results.total_count
+
pagy = Pagy.new(vars)
# with :last_page overflow we need to re-run the method in order to get the hits
- if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
- return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page))
- end
- return pagy, called.empty? ? results : results.send(*called)
+ return pagy_searchkick(pagy_search_args, vars.merge(page: pagy.page)) \
+ if defined?(Pagy::UseOverflowExtra) && pagy.overflow? && pagy.vars[:overflow] == :last_page
+
+ [ pagy, called.empty? ? results : results.send(*called) ]
end
# Sub-method called only by #pagy_searchkick: here for easy customization of variables by overriding
diff --git a/lib/pagy/extras/semantic.rb b/lib/pagy/extras/semantic.rb
index 55685be51..9b20be3f2 100644
--- a/lib/pagy/extras/semantic.rb
+++ b/lib/pagy/extras/semantic.rb
@@ -1,5 +1,4 @@
# See the Pagy documentation: https://ddnexus.github.io/pagy/extras/semantic
-# encoding: utf-8
# frozen_string_literal: true
require 'pagy/extras/shared'
@@ -9,47 +8,69 @@ module Frontend
# Pagination for semantic: it returns the html with the series of links to the pages
def pagy_semantic_nav(pagy)
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
+ link = pagy_link_proc(pagy, 'class="item"')
- html = (p_prev ? %(#{link.call p_prev, '', 'aria-label="previous"'})
- : +%(
))
+ html = +%(
)
+ html << pagy_semantic_prev_html(pagy, link)
pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
- html << if item.is_a?(Integer); %(#{link.call item}) # page link
- elsif item.is_a?(String) ; %(#{item}) # current page
- elsif item == :gap ; %(
...
) # page gap
+ html << case item
+ when Integer then link.call item # page link
+ when String then %(#{item}) # current page
+ when :gap then %(
...
) # page gap
end
end
- html << (p_next ? %(#{link.call p_next, '', 'aria-label="next"'})
- : %(
))
- %(
#{html}
)
+ html << pagy_semantic_next_html(pagy, link)
+ html << %(
)
end
# Javascript pagination for semantic: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_semantic_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next
- tags = { 'before' => (p_prev ? %(#{link.call(p_prev, '', 'aria-label="previous"')})
- : %(
)) }
- %(#{pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)})
+ 'after' => pagy_semantic_next_html(pagy, link) }
+
+ html = %()
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Combo pagination for semantic: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_semantic_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy, 'class="item"'), pagy.prev, pagy.next, pagy.page, pagy.pages
-
- html = %(
)
+ html << pagy_uikit_next_html(pagy, link)
+ html << %(
)
end
# Javascript pagination for uikit: it returns a nav and a JSON tag used by the Pagy.nav javascript
def pagy_uikit_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next = pagy_link_proc(pagy), pagy.prev, pagy.next
- previous_span = "#{pagy_t('pagy.nav.prev')}"
- next_span = "#{pagy_t('pagy.nav.next')}"
- tags = { 'before' => p_prev ? %(
)
+ html << pagy_json_tag(pagy, :nav, id, tags, pagy.sequels)
end
# Javascript combo pagination for uikit: it returns a nav and a JSON tag used by the Pagy.combo_nav javascript
def pagy_uikit_combo_nav_js(pagy, id=pagy_id)
- link, p_prev, p_next, p_page, p_pages = pagy_link_proc(pagy), pagy.prev, pagy.next, pagy.page, pagy.pages
+ link = pagy_link_proc(pagy)
+ p_page = pagy.page
+ p_pages = pagy.pages
+ input = %()
+
+ %(
#{
+ if (p_prev = pagy.prev)
+ link.call p_prev, pagy_t('pagy.nav.prev'), 'class="uk-button uk-button-default"'
+ else
+ %()
+ end
+ }