pagy 43.2.3 → 43.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/apps/calendar.ru +5 -6
- data/apps/demo.ru +1 -1
- data/apps/enable_rails_page_segment.rb +6 -2
- data/apps/keynav+root_key.ru +4 -5
- data/apps/keynav.ru +6 -7
- data/apps/keyset.ru +3 -5
- data/apps/keyset_sequel.ru +3 -5
- data/apps/rails.ru +3 -4
- data/apps/repro.ru +5 -6
- data/config/pagy.rb +1 -1
- data/javascripts/pagy.js +2 -2
- data/javascripts/pagy.js.map +2 -2
- data/javascripts/pagy.min.js +1 -1
- data/javascripts/pagy.mjs +1 -1
- data/lib/pagy/classes/calendar/calendar.rb +31 -25
- data/lib/pagy/classes/calendar/unit.rb +7 -4
- data/lib/pagy/classes/exceptions.rb +1 -0
- data/lib/pagy/classes/keyset/adapters/active_record.rb +3 -1
- data/lib/pagy/classes/keyset/adapters/sequel.rb +3 -1
- data/lib/pagy/classes/keyset/keynav.rb +3 -0
- data/lib/pagy/classes/keyset/keyset.rb +13 -17
- data/lib/pagy/classes/offset/countless.rb +10 -3
- data/lib/pagy/classes/offset/offset.rb +6 -1
- data/lib/pagy/classes/request.rb +10 -7
- data/lib/pagy/modules/abilities/configurable.rb +1 -1
- data/lib/pagy/modules/abilities/countable.rb +1 -0
- data/lib/pagy/modules/abilities/linkable.rb +19 -12
- data/lib/pagy/modules/abilities/rangeable.rb +0 -1
- data/lib/pagy/modules/b64.rb +8 -2
- data/lib/pagy/modules/console.rb +15 -6
- data/lib/pagy/modules/i18n/i18n.rb +11 -4
- data/lib/pagy/modules/searcher.rb +8 -4
- data/lib/pagy/toolbox/helpers/data_hash.rb +1 -0
- data/lib/pagy/toolbox/helpers/headers_hash.rb +2 -1
- data/lib/pagy/toolbox/helpers/info_tag.rb +2 -0
- data/lib/pagy/toolbox/helpers/input_nav_js.rb +1 -0
- data/lib/pagy/toolbox/helpers/page_url.rb +1 -0
- data/lib/pagy/toolbox/helpers/series_nav.rb +1 -0
- data/lib/pagy/toolbox/helpers/series_nav_js.rb +1 -0
- data/lib/pagy/toolbox/helpers/support/a_lambda.rb +1 -1
- data/lib/pagy/toolbox/paginators/calendar.rb +9 -6
- data/lib/pagy/toolbox/paginators/countish.rb +6 -3
- data/lib/pagy/toolbox/paginators/countless.rb +5 -2
- data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +12 -6
- data/lib/pagy/toolbox/paginators/keynav_js.rb +5 -3
- data/lib/pagy/toolbox/paginators/keyset.rb +2 -1
- data/lib/pagy/toolbox/paginators/meilisearch.rb +10 -7
- data/lib/pagy/toolbox/paginators/method.rb +7 -5
- data/lib/pagy/toolbox/paginators/offset.rb +9 -2
- data/lib/pagy/toolbox/paginators/searchkick.rb +12 -9
- data/lib/pagy.rb +1 -1
- metadata +1 -1
|
@@ -13,7 +13,7 @@ class Pagy
|
|
|
13
13
|
autoload :Sequel, path.join('adapters/sequel')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
autoload :Keynav,
|
|
16
|
+
autoload :Keynav, Pathname.new(__dir__).join('keynav')
|
|
17
17
|
|
|
18
18
|
# Define empty subclasses to allow specific typing without triggering autoload
|
|
19
19
|
class ActiveRecord < self; end
|
|
@@ -27,28 +27,24 @@ class Pagy
|
|
|
27
27
|
if /::(?:ActiveRecord|Sequel)$/.match?(name)
|
|
28
28
|
# Ensure the adapter is mixed in (lazy load)
|
|
29
29
|
mix_in_adapter(name.split('::').last)
|
|
30
|
-
return allocate.tap {
|
|
30
|
+
return allocate.tap { _1.send(:initialize, set, **) }
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# 2. Handle Factory usage (Pagy::Keyset.new)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
subclass = const_get(orm_name)
|
|
44
|
-
# Ensure the adapter is mixed in (lazy load)
|
|
45
|
-
subclass.mix_in_adapter(orm_name)
|
|
46
|
-
subclass.new(set, **)
|
|
34
|
+
adapter = if defined?(::ActiveRecord) && set.is_a?(::ActiveRecord::Relation)
|
|
35
|
+
:ActiveRecord
|
|
36
|
+
elsif defined?(::Sequel) && set.is_a?(::Sequel::Dataset)
|
|
37
|
+
:Sequel
|
|
38
|
+
else
|
|
39
|
+
raise TypeError, "expected an ActiveRecord::Relation or Sequel::Dataset; got #{set.class}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
const_get(adapter).tap { _1.mix_in_adapter(adapter) }.new(set, **)
|
|
47
43
|
end
|
|
48
44
|
|
|
49
45
|
# Helper to lazy-include the adapter module
|
|
50
|
-
def self.mix_in_adapter(
|
|
51
|
-
adapter_module =
|
|
46
|
+
def self.mix_in_adapter(adapter)
|
|
47
|
+
adapter_module = Adapters.const_get(adapter)
|
|
52
48
|
include(adapter_module) unless self < adapter_module
|
|
53
49
|
end
|
|
54
50
|
|
|
@@ -34,15 +34,20 @@ class Pagy
|
|
|
34
34
|
def finalize(fetched_size)
|
|
35
35
|
# empty records (trigger the right info message for known 0 count)
|
|
36
36
|
@count = 0 if fetched_size.zero? && @page == 1
|
|
37
|
-
return self unless in_range? { fetched_size.positive? || @page == 1 }
|
|
38
37
|
|
|
39
|
-
|
|
38
|
+
unless in_range? { fetched_size.positive? || @page == 1 }
|
|
39
|
+
assign_empty_page_variables
|
|
40
|
+
return self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
past = @last && @page < @last # current page is before the known last page
|
|
40
44
|
more = fetched_size > @limit # more pages after this one
|
|
41
45
|
@last = upto_max_pages(more ? @page + 1 : @page) unless past && more
|
|
42
46
|
@in = [fetched_size, @limit].min
|
|
43
47
|
@from = @in.zero? ? 0 : @offset + 1
|
|
44
48
|
@to = @offset + @in
|
|
45
49
|
assign_previous_and_next
|
|
50
|
+
|
|
46
51
|
self
|
|
47
52
|
end
|
|
48
53
|
|
|
@@ -55,7 +60,9 @@ class Pagy
|
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
# Support easy countless page param overriding (for legacy param and behavior)
|
|
58
|
-
def compose_page_param(page)
|
|
63
|
+
def compose_page_param(page)
|
|
64
|
+
EscapedValue.new("#{page || 1}+#{@last}")
|
|
65
|
+
end
|
|
59
66
|
end
|
|
60
67
|
end
|
|
61
68
|
end
|
|
@@ -19,11 +19,16 @@ class Pagy
|
|
|
19
19
|
assign_and_check(limit: 1, count: 0, page: 1)
|
|
20
20
|
assign_last
|
|
21
21
|
assign_offset
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
unless in_range? { @page <= @last }
|
|
24
|
+
assign_empty_page_variables
|
|
25
|
+
return
|
|
26
|
+
end
|
|
23
27
|
|
|
24
28
|
@from = [@offset + 1, @count].min
|
|
25
29
|
@to = [@offset + @limit, @count].min
|
|
26
30
|
@in = [@to - @from + 1, @count].min
|
|
31
|
+
|
|
27
32
|
assign_previous_and_next
|
|
28
33
|
end
|
|
29
34
|
|
data/lib/pagy/classes/request.rb
CHANGED
|
@@ -13,6 +13,7 @@ class Pagy
|
|
|
13
13
|
else
|
|
14
14
|
[request.base_url, request.path, get_params(request), request.cookies['pagy']]
|
|
15
15
|
end
|
|
16
|
+
freeze
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
attr_reader :base_url, :path, :params, :cookie
|
|
@@ -20,21 +21,23 @@ class Pagy
|
|
|
20
21
|
def resolve_page(force_integer: true)
|
|
21
22
|
page_key = @options[:page_key] || DEFAULT[:page_key]
|
|
22
23
|
page = @params.dig(@options[:root_key], page_key) || @params[page_key]
|
|
23
|
-
|
|
24
|
-
force_integer ? (page || 1).to_i : page
|
|
24
|
+
force_integer ? [page.to_i, 1].max : page
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def resolve_limit
|
|
28
28
|
limit_key = @options[:limit_key] || DEFAULT[:limit_key]
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
default = @options[:limit] || DEFAULT[:limit]
|
|
30
|
+
max_limit = @options[:client_max_limit]
|
|
31
|
+
return default unless max_limit
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
limit = @params.dig(@options[:root_key], limit_key) || @params[limit_key]
|
|
34
|
+
limit ? [limit.to_i, max_limit].min : default
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
private
|
|
37
38
|
|
|
38
|
-
def get_params(request)
|
|
39
|
+
def get_params(request)
|
|
40
|
+
request.GET.merge(request.POST).to_h.freeze
|
|
41
|
+
end
|
|
39
42
|
end
|
|
40
43
|
end
|
|
@@ -38,26 +38,33 @@ class Pagy
|
|
|
38
38
|
|
|
39
39
|
protected
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# Overridable by classes with composite page param
|
|
42
42
|
def compose_page_param(page) = page
|
|
43
43
|
|
|
44
44
|
# Return the URL for the page, relying on the Pagy::Request
|
|
45
45
|
def compose_page_url(page, **options)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
opts = @options.merge(options)
|
|
47
|
+
params = @request.params.clone(freeze: false)
|
|
48
|
+
root_key = opts[:root_key]
|
|
49
|
+
container = if root_key
|
|
50
|
+
params[root_key] = params[root_key]&.clone(freeze: false) || {}
|
|
51
|
+
else
|
|
52
|
+
params
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
{ opts[:page_key] => compose_page_param(page),
|
|
56
|
+
opts[:limit_key] => opts[:client_max_limit] && opts[:limit] }.each do |k, v|
|
|
57
|
+
v ? container[k] = v : container.delete(k)
|
|
53
58
|
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
|
|
60
|
+
opts[:querify]&.(params) # Must modify the params: the returned value is ignored
|
|
61
|
+
fragment = opts[:fragment].to_s.sub(/\A(?=[^#])/, '#') # conditionally prepend '#'
|
|
62
|
+
|
|
63
|
+
compose_url(opts[:absolute], opts[:path], params, fragment)
|
|
57
64
|
end
|
|
58
65
|
|
|
59
66
|
def compose_url(absolute, path, params, fragment)
|
|
60
|
-
query_string = QueryUtils.build_nested_query(params).sub(/\A(?=.)/, '?')
|
|
67
|
+
query_string = QueryUtils.build_nested_query(params).sub(/\A(?=.)/, '?') # conditionally prepend '?'
|
|
61
68
|
"#{@request.base_url if absolute}#{path || @request.path}#{query_string}#{fragment}"
|
|
62
69
|
end
|
|
63
70
|
end
|
data/lib/pagy/modules/b64.rb
CHANGED
|
@@ -5,14 +5,19 @@ class Pagy
|
|
|
5
5
|
module B64
|
|
6
6
|
module_function
|
|
7
7
|
|
|
8
|
-
def encode(bin)
|
|
8
|
+
def encode(bin)
|
|
9
|
+
[bin].pack('m0')
|
|
10
|
+
end
|
|
9
11
|
|
|
10
|
-
def decode(str)
|
|
12
|
+
def decode(str)
|
|
13
|
+
str.unpack1('m0')
|
|
14
|
+
end
|
|
11
15
|
|
|
12
16
|
def urlsafe_encode(bin)
|
|
13
17
|
str = encode(bin)
|
|
14
18
|
str.chomp!('==') or str.chomp!('=')
|
|
15
19
|
str.tr!('+/', '-_')
|
|
20
|
+
|
|
16
21
|
str
|
|
17
22
|
end
|
|
18
23
|
|
|
@@ -23,6 +28,7 @@ class Pagy
|
|
|
23
28
|
else
|
|
24
29
|
str = str.tr('-_', '+/')
|
|
25
30
|
end
|
|
31
|
+
|
|
26
32
|
decode(str)
|
|
27
33
|
end
|
|
28
34
|
end
|
data/lib/pagy/modules/console.rb
CHANGED
|
@@ -9,16 +9,25 @@ class Pagy
|
|
|
9
9
|
@collection = clone
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def offset(value)
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
def offset(value)
|
|
13
|
+
tap { @collection = self[value..] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def limit(value)
|
|
17
|
+
@collection[0, value]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def count(*) = size
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
include Method
|
|
18
24
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
def request
|
|
26
|
+
@request ||= { base_url: 'http://www.example.com', path: '/path', params: { example: '123' } }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def params = request[:params]
|
|
30
|
+
|
|
22
31
|
def collection = Collection
|
|
23
32
|
end
|
|
24
33
|
end
|
|
@@ -8,15 +8,22 @@ class Pagy
|
|
|
8
8
|
module I18n
|
|
9
9
|
extend self
|
|
10
10
|
|
|
11
|
-
def pathnames
|
|
12
|
-
|
|
11
|
+
def pathnames
|
|
12
|
+
@pathnames ||= [ROOT.join('locales')]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def locales
|
|
16
|
+
@locales ||= {}
|
|
17
|
+
end
|
|
13
18
|
|
|
14
19
|
# Store the variable for the duration of a single request
|
|
15
20
|
def locale=(value)
|
|
16
|
-
Thread.current[:pagy_locale] = value
|
|
21
|
+
Thread.current[:pagy_locale] = value.to_s
|
|
17
22
|
end
|
|
18
23
|
|
|
19
|
-
def locale
|
|
24
|
+
def locale
|
|
25
|
+
Thread.current[:pagy_locale] || 'en'
|
|
26
|
+
end
|
|
20
27
|
|
|
21
28
|
# Translate and pluralize the key with the locale entries
|
|
22
29
|
def translate(key, **options)
|
|
@@ -6,12 +6,16 @@ class Pagy
|
|
|
6
6
|
module_function
|
|
7
7
|
|
|
8
8
|
# Common search logic
|
|
9
|
-
def wrap(
|
|
9
|
+
def wrap(search_arguments, options)
|
|
10
10
|
options[:page] ||= options[:request].resolve_page
|
|
11
11
|
options[:limit] = options[:request].resolve_limit
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
|
|
13
|
+
pagy, results = yield
|
|
14
|
+
|
|
15
|
+
arguments = search_arguments[4..]
|
|
16
|
+
results = results.send(*arguments) unless arguments.empty?
|
|
17
|
+
|
|
18
|
+
[pagy, results]
|
|
15
19
|
end
|
|
16
20
|
end
|
|
17
21
|
end
|
|
@@ -9,6 +9,7 @@ class Pagy
|
|
|
9
9
|
template = compose_page_url(PAGE_TOKEN, **)
|
|
10
10
|
to_url = ->(page) { template.sub(PAGE_TOKEN, page.to_s) if page }
|
|
11
11
|
data_keys -= %i[count limit] if calendar?
|
|
12
|
+
|
|
12
13
|
data_keys.each_with_object({}) do |key, data|
|
|
13
14
|
value = case key
|
|
14
15
|
when :url_template then template
|
|
@@ -4,7 +4,7 @@ require_relative 'urls_hash'
|
|
|
4
4
|
|
|
5
5
|
# Add pagination response headers
|
|
6
6
|
class Pagy
|
|
7
|
-
DEFAULT_HEADERS_MAP = { page:
|
|
7
|
+
DEFAULT_HEADERS_MAP = { page: 'current-page',
|
|
8
8
|
limit: 'page-limit',
|
|
9
9
|
count: 'total-count',
|
|
10
10
|
pages: 'total-pages' }.freeze
|
|
@@ -12,6 +12,7 @@ class Pagy
|
|
|
12
12
|
# Generate a hash of RFC-8288-compliant http headers
|
|
13
13
|
def headers_hash(headers_map: @options[:headers_map] || DEFAULT_HEADERS_MAP, **)
|
|
14
14
|
links = urls_hash(**, absolute: true).map { %(<#{_2}>; rel="#{_1}") }.join(', ')
|
|
15
|
+
|
|
15
16
|
headers_map.each_with_object('link' => links) do |(key, name), hash|
|
|
16
17
|
next unless name
|
|
17
18
|
|
|
@@ -13,6 +13,7 @@ class Pagy
|
|
|
13
13
|
else
|
|
14
14
|
'pagy.info_tag.multiple_pages'
|
|
15
15
|
end
|
|
16
|
+
|
|
16
17
|
info_data = if @count.nil?
|
|
17
18
|
{ page: @page, pages: @last }
|
|
18
19
|
else
|
|
@@ -21,6 +22,7 @@ class Pagy
|
|
|
21
22
|
from: @from,
|
|
22
23
|
to: @to }
|
|
23
24
|
end
|
|
25
|
+
|
|
24
26
|
%(<span#{%( id="#{id}") if id} class="pagy info">#{I18n.translate(i18n_key, **info_data)}</span>)
|
|
25
27
|
end
|
|
26
28
|
end
|
|
@@ -13,6 +13,7 @@ class Pagy
|
|
|
13
13
|
current: %(<a role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a>),
|
|
14
14
|
gap: %(<a role="separator" aria-disabled="true">#{I18n.translate('pagy.gap')}</a>),
|
|
15
15
|
after: next_tag(a_lambda) }
|
|
16
|
+
|
|
16
17
|
wrap_series_nav_js(tokens, 'pagy series-nav-js', **)
|
|
17
18
|
end
|
|
18
19
|
end
|
|
@@ -13,7 +13,7 @@ class Pagy
|
|
|
13
13
|
|
|
14
14
|
# Return a performance optimized lambda to generate the anchor tag
|
|
15
15
|
# Benchmarked on a 20 link nav: it is ~22x faster and uses ~18x less memory than rails' link_to
|
|
16
|
-
def a_lambda(anchor_string:
|
|
16
|
+
def a_lambda(anchor_string: @options[:anchor_string], **)
|
|
17
17
|
left, right = %(<a href="#{compose_page_url(PAGE_TOKEN, **)}"#{
|
|
18
18
|
%( #{anchor_string}) if anchor_string}).split(PAGE_TOKEN, 2)
|
|
19
19
|
|
|
@@ -12,15 +12,18 @@ class Pagy
|
|
|
12
12
|
unless config.is_a?(Hash) && (config.keys - allowed_options).empty?
|
|
13
13
|
|
|
14
14
|
config[:offset] ||= {}
|
|
15
|
+
|
|
15
16
|
unless config[:disabled]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
period = pagy_calendar_period(collection)
|
|
18
|
+
params = config[:request].params
|
|
19
|
+
|
|
20
|
+
calendar, from, to = Calendar.send(:init, config, period, params) do |unit, unit_period|
|
|
21
|
+
pagy_calendar_counts(collection, unit, *unit_period) if respond_to?(:pagy_calendar_counts)
|
|
22
|
+
end
|
|
23
|
+
|
|
22
24
|
collection = pagy_calendar_filter(collection, from, to)
|
|
23
25
|
end
|
|
26
|
+
|
|
24
27
|
pagy, records = pagy(:offset, collection, **config[:offset])
|
|
25
28
|
[calendar, pagy, records]
|
|
26
29
|
end
|
|
@@ -9,26 +9,29 @@ class Pagy
|
|
|
9
9
|
# Return the Offset::Countish instance and records
|
|
10
10
|
def paginate(collection, options)
|
|
11
11
|
options[:page] ||= options[:request].resolve_page(force_integer: false)
|
|
12
|
+
|
|
12
13
|
if options[:page].is_a?(String)
|
|
13
14
|
page, count, epoch = options[:page].split.map(&:to_i)
|
|
14
15
|
options[:page] = page
|
|
15
16
|
end
|
|
17
|
+
|
|
16
18
|
setup_options(count, epoch, collection, options)
|
|
17
19
|
options[:limit] = options[:request].resolve_limit
|
|
18
|
-
|
|
20
|
+
|
|
21
|
+
pagy = Offset::Countish.new(**options)
|
|
19
22
|
[pagy, pagy.records(collection)]
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
# Get the count from the page and set epoch when ttl (Time To Live) requires it
|
|
23
26
|
def setup_options(count, epoch, collection, options)
|
|
24
27
|
now = Time.now.to_i
|
|
28
|
+
|
|
25
29
|
if !options[:count] && count && (!options[:ttl] ||
|
|
26
30
|
(epoch && epoch <= now && now < (epoch + options[:ttl]))) # ongoing
|
|
27
|
-
# puts 'ongoing'
|
|
28
31
|
options[:count] = count
|
|
29
32
|
options[:epoch] = epoch if options[:ttl]
|
|
33
|
+
|
|
30
34
|
else # recount
|
|
31
|
-
# puts 'recount'
|
|
32
35
|
options[:count] ||= Countable.get_count(collection, options)
|
|
33
36
|
options[:epoch] = now if options[:ttl]
|
|
34
37
|
end
|
|
@@ -7,13 +7,16 @@ class Pagy
|
|
|
7
7
|
# Return the Offset::Countless instance and records
|
|
8
8
|
def paginate(collection, options)
|
|
9
9
|
options[:page] ||= options[:request].resolve_page(force_integer: false) # accept nil and strings
|
|
10
|
+
|
|
10
11
|
if options[:page].is_a?(String)
|
|
11
|
-
page, last = options[:page].split.map(&:to_i) #
|
|
12
|
+
page, last = options[:page].split.map(&:to_i) # ' ' separator, (encoded as '+' by Countless#compose_page_param)
|
|
12
13
|
options[:page] = page
|
|
13
14
|
options[:last] = last if last&.positive?
|
|
14
15
|
end
|
|
16
|
+
|
|
15
17
|
options[:limit] = options[:request].resolve_limit
|
|
16
|
-
|
|
18
|
+
|
|
19
|
+
pagy = Offset::Countless.new(**options)
|
|
17
20
|
[pagy, pagy.records(collection)]
|
|
18
21
|
end
|
|
19
22
|
end
|
|
@@ -8,22 +8,26 @@ class Pagy
|
|
|
8
8
|
|
|
9
9
|
# Paginate from the search object
|
|
10
10
|
def paginate(search, options)
|
|
11
|
-
if search.is_a?(Search::Arguments)
|
|
12
|
-
|
|
11
|
+
if search.is_a?(Search::Arguments) # Active mode
|
|
12
|
+
|
|
13
13
|
Searcher.wrap(search, options) do
|
|
14
14
|
model, query_or_payload, search_options = search
|
|
15
15
|
search_options[:size] = options[:limit]
|
|
16
16
|
search_options[:from] = options[:limit] * ((options[:page] || 1) - 1)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
method = options[:search_method] || ElasticsearchRails::DEFAULT[:search_method]
|
|
19
|
+
response_object = model.send(method, query_or_payload, **search_options)
|
|
20
|
+
options[:count] = total_count_from(response_object)
|
|
21
|
+
|
|
20
22
|
[ElasticsearchRails.new(**options), response_object]
|
|
21
23
|
end
|
|
22
|
-
|
|
24
|
+
|
|
25
|
+
else # Passive mode
|
|
23
26
|
from, size = pagination_params_from(search)
|
|
24
27
|
options[:limit] = size
|
|
25
28
|
options[:page] = ((from || 0) / options[:limit]) + 1
|
|
26
29
|
options[:count] = total_count_from(search)
|
|
30
|
+
|
|
27
31
|
ElasticsearchRails.new(**options)
|
|
28
32
|
end
|
|
29
33
|
end
|
|
@@ -36,6 +40,7 @@ class Pagy
|
|
|
36
40
|
from = (container[:from] || container['from']).to_i
|
|
37
41
|
size = (container[:size] || container['size']).to_i
|
|
38
42
|
size = 10 if size.zero?
|
|
43
|
+
|
|
39
44
|
[from, size]
|
|
40
45
|
end
|
|
41
46
|
|
|
@@ -44,6 +49,7 @@ class Pagy
|
|
|
44
49
|
total = response_object.instance_eval do
|
|
45
50
|
respond_to?(:response) ? response['hits']['total'] : raw_response['hits']['total']
|
|
46
51
|
end
|
|
52
|
+
|
|
47
53
|
total.is_a?(Hash) ? total['value'] : total
|
|
48
54
|
end
|
|
49
55
|
end
|
|
@@ -10,15 +10,17 @@ class Pagy
|
|
|
10
10
|
# Fall back to :countless if the :page has no client data.
|
|
11
11
|
def paginate(set, options)
|
|
12
12
|
page = options[:request].resolve_page(force_integer: false) # allow nil
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
return CountlessPaginator.paginate(set, page:, **options) if page&.match(' ') # countless fallback
|
|
15
|
+
|
|
16
|
+
if page.is_a?(String) # keynav page param
|
|
16
17
|
page_arguments = JSON.parse(B64.urlsafe_decode(page))
|
|
17
18
|
# Restart the pagination from page 1/nil if the url has been requested from another browser
|
|
18
19
|
options[:page] = page_arguments if options[:request].cookie == page_arguments.shift
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
options[:limit] = options[:request].resolve_limit
|
|
23
|
+
|
|
22
24
|
pagy = Keyset::Keynav.new(set, **options)
|
|
23
25
|
[pagy, pagy.records]
|
|
24
26
|
end
|
|
@@ -8,7 +8,8 @@ class Pagy
|
|
|
8
8
|
def paginate(set, options)
|
|
9
9
|
options[:page] ||= options[:request].resolve_page(force_integer: false) # allow nil
|
|
10
10
|
options[:limit] = options[:request].resolve_limit
|
|
11
|
-
pagy
|
|
11
|
+
pagy = Keyset.new(set, **options)
|
|
12
|
+
|
|
12
13
|
[pagy, pagy.records]
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -8,22 +8,25 @@ class Pagy
|
|
|
8
8
|
|
|
9
9
|
# Paginate from the search object
|
|
10
10
|
def paginate(search, options)
|
|
11
|
-
if search.is_a?(Search::Arguments)
|
|
12
|
-
|
|
11
|
+
if search.is_a?(Search::Arguments) # Active mode
|
|
12
|
+
|
|
13
13
|
Searcher.wrap(search, options) do
|
|
14
14
|
model, term, search_options = search
|
|
15
15
|
search_options[:hits_per_page] = options[:limit]
|
|
16
16
|
search_options[:page] = options[:page]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
method = options[:search_method] || Meilisearch::DEFAULT[:search_method]
|
|
19
|
+
results = model.send(method, term, search_options)
|
|
20
|
+
options[:count] = results.raw_answer['totalHits']
|
|
21
|
+
|
|
20
22
|
[Meilisearch.new(**options), results]
|
|
21
23
|
end
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
else # Passive mode
|
|
24
26
|
options[:limit] = search.raw_answer['hitsPerPage']
|
|
25
27
|
options[:page] = search.raw_answer['page']
|
|
26
28
|
options[:count] = search.raw_answer['totalHits']
|
|
29
|
+
|
|
27
30
|
Meilisearch.new(**options)
|
|
28
31
|
end
|
|
29
32
|
end
|
|
@@ -21,14 +21,16 @@ class Pagy
|
|
|
21
21
|
protected
|
|
22
22
|
|
|
23
23
|
define_method :pagy do |paginator = :offset, collection, **options|
|
|
24
|
-
arguments
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
arguments = if paginator == :calendar
|
|
25
|
+
[self, collection, options]
|
|
26
|
+
else
|
|
27
|
+
[collection, options = Pagy.options.merge(options)]
|
|
28
|
+
end
|
|
29
|
+
|
|
29
30
|
options[:root_key] = 'page' if options[:jsonapi] # enforce 'page' root_key for JSON:API
|
|
30
31
|
options[:request] ||= request # user set request or self.request
|
|
31
32
|
options[:request] = Request.new(options) # Pagy::Request
|
|
33
|
+
|
|
32
34
|
Pagy.const_get(paginators[paginator]).paginate(*arguments)
|
|
33
35
|
end
|
|
34
36
|
end
|