pagy 43.0.0 → 43.3.0

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/apps/calendar.ru +11 -12
  4. data/apps/demo.ru +5 -5
  5. data/apps/enable_rails_page_segment.rb +54 -0
  6. data/apps/index.rb +1 -1
  7. data/apps/keynav+root_key.ru +316 -0
  8. data/apps/keynav.ru +10 -13
  9. data/apps/keyset.ru +5 -11
  10. data/apps/keyset_sequel.ru +10 -12
  11. data/apps/rails.ru +8 -12
  12. data/apps/repro.ru +11 -11
  13. data/bin/pagy +2 -94
  14. data/config/pagy.rb +8 -7
  15. data/javascripts/ai_widget.js +65 -51
  16. data/javascripts/pagy.js +20 -17
  17. data/javascripts/pagy.js.map +3 -3
  18. data/javascripts/pagy.min.js +2 -1
  19. data/javascripts/pagy.mjs +19 -16
  20. data/javascripts/wand.js +15 -9
  21. data/lib/pagy/classes/calendar/calendar.rb +36 -31
  22. data/lib/pagy/classes/calendar/day.rb +1 -1
  23. data/lib/pagy/classes/calendar/month.rb +1 -1
  24. data/lib/pagy/classes/calendar/quarter.rb +1 -1
  25. data/lib/pagy/classes/calendar/unit.rb +12 -13
  26. data/lib/pagy/classes/calendar/year.rb +1 -1
  27. data/lib/pagy/classes/exceptions.rb +1 -8
  28. data/lib/pagy/classes/keyset/adapters/active_record.rb +3 -1
  29. data/lib/pagy/classes/keyset/adapters/sequel.rb +3 -1
  30. data/lib/pagy/classes/keyset/keynav.rb +9 -4
  31. data/lib/pagy/classes/keyset/keyset.rb +57 -32
  32. data/lib/pagy/classes/offset/countish.rb +17 -0
  33. data/lib/pagy/classes/offset/countless.rb +26 -14
  34. data/lib/pagy/classes/offset/offset.rb +8 -2
  35. data/lib/pagy/classes/offset/search.rb +6 -10
  36. data/lib/pagy/classes/request.rb +29 -20
  37. data/lib/pagy/cli.rb +135 -0
  38. data/lib/pagy/console.rb +6 -0
  39. data/lib/pagy/modules/abilities/configurable.rb +2 -2
  40. data/lib/pagy/modules/abilities/countable.rb +24 -0
  41. data/lib/pagy/modules/abilities/linkable.rb +35 -24
  42. data/lib/pagy/modules/abilities/rangeable.rb +3 -3
  43. data/lib/pagy/modules/b64.rb +9 -3
  44. data/lib/pagy/modules/console.rb +15 -20
  45. data/lib/pagy/modules/i18n/i18n.rb +38 -14
  46. data/lib/pagy/modules/i18n/p11n/arabic.rb +1 -0
  47. data/lib/pagy/modules/i18n/p11n/east_slavic.rb +1 -0
  48. data/lib/pagy/modules/i18n/p11n/polish.rb +1 -0
  49. data/lib/pagy/modules/searcher.rb +9 -8
  50. data/lib/pagy/toolbox/helpers/anchor_tags.rb +11 -15
  51. data/lib/pagy/toolbox/helpers/bootstrap/input_nav_js.rb +3 -0
  52. data/lib/pagy/toolbox/helpers/bootstrap/series_nav.rb +3 -1
  53. data/lib/pagy/toolbox/helpers/bootstrap/series_nav_js.rb +2 -0
  54. data/lib/pagy/toolbox/helpers/bulma/input_nav_js.rb +3 -0
  55. data/lib/pagy/toolbox/helpers/bulma/previous_next_html.rb +1 -1
  56. data/lib/pagy/toolbox/helpers/bulma/series_nav.rb +3 -1
  57. data/lib/pagy/toolbox/helpers/bulma/series_nav_js.rb +2 -0
  58. data/lib/pagy/toolbox/helpers/data_hash.rb +19 -17
  59. data/lib/pagy/toolbox/helpers/headers_hash.rb +15 -9
  60. data/lib/pagy/toolbox/helpers/info_tag.rb +2 -0
  61. data/lib/pagy/toolbox/helpers/input_nav_js.rb +9 -6
  62. data/lib/pagy/toolbox/helpers/limit_tag_js.rb +4 -3
  63. data/lib/pagy/toolbox/helpers/loader.rb +3 -0
  64. data/lib/pagy/toolbox/helpers/page_url.rb +10 -16
  65. data/lib/pagy/toolbox/helpers/series_nav.rb +5 -4
  66. data/lib/pagy/toolbox/helpers/series_nav_js.rb +2 -1
  67. data/lib/pagy/toolbox/helpers/support/a_lambda.rb +8 -6
  68. data/lib/pagy/toolbox/helpers/support/data_pagy_attribute.rb +6 -1
  69. data/lib/pagy/toolbox/helpers/support/series.rb +1 -2
  70. data/lib/pagy/toolbox/helpers/support/wrap_input_nav_js.rb +1 -1
  71. data/lib/pagy/toolbox/helpers/support/wrap_series_nav.rb +2 -1
  72. data/lib/pagy/toolbox/helpers/support/wrap_series_nav_js.rb +10 -4
  73. data/lib/pagy/toolbox/helpers/urls_hash.rb +7 -7
  74. data/lib/pagy/toolbox/paginators/calendar.rb +13 -9
  75. data/lib/pagy/toolbox/paginators/countish.rb +39 -0
  76. data/lib/pagy/toolbox/paginators/countless.rb +13 -15
  77. data/lib/pagy/toolbox/paginators/elasticsearch_rails.rb +43 -18
  78. data/lib/pagy/toolbox/paginators/keynav_js.rb +14 -15
  79. data/lib/pagy/toolbox/paginators/keyset.rb +7 -9
  80. data/lib/pagy/toolbox/paginators/meilisearch.rb +21 -18
  81. data/lib/pagy/toolbox/paginators/method.rb +15 -3
  82. data/lib/pagy/toolbox/paginators/offset.rb +14 -22
  83. data/lib/pagy/toolbox/paginators/searchkick.rb +21 -18
  84. data/lib/pagy/toolbox/paginators/typesense_rails.rb +35 -0
  85. data/lib/pagy.rb +23 -10
  86. data/locales/id.yml +1 -3
  87. data/locales/ja.yml +1 -3
  88. data/locales/km.yml +1 -3
  89. data/locales/sw.yml +2 -2
  90. data/locales/tr.yml +10 -8
  91. data/stylesheets/pagy-tailwind.css +1 -1
  92. data/stylesheets/pagy.css +1 -6
  93. metadata +25 -8
  94. data/lib/optimist.rb +0 -1022
  95. data/lib/pagy/classes/keyset/active_record.rb +0 -11
  96. data/lib/pagy/classes/keyset/keynav/active_record.rb +0 -13
  97. data/lib/pagy/classes/keyset/keynav/sequel.rb +0 -13
  98. data/lib/pagy/classes/keyset/sequel.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66a384673ddf0542be2e0a2b39001fef7780ef67fa39d5a1b0cf2f8b94e01761
4
- data.tar.gz: 564de9f2bd8c03bb1fa58226ee2a4c42f11c6e1dc9a3ed14ae6264f8f45186d3
3
+ metadata.gz: 384cf9e4eb056f151267e5628f61a18cda32dd4243234ca57f3dc98db3bada58
4
+ data.tar.gz: f8d58e124b0d6ffcef9bbd36e575ef14db069488180728ec73460a4c3ff17563
5
5
  SHA512:
6
- metadata.gz: 340e0c7178341b87c86d6930a60d6c1e3a25989f992193aacd0bb82b3f6631d0fba81f0d95d3c37db27bae971f8bd9a6db60194fa3cfc7c1e9bfde9294b360ef
7
- data.tar.gz: 46a3dfdf18bc20ba1d86eccb7d9883abfd5666ce4b3c2f5b1de9dbaa3583412e1da6544117074554088b64dc0b119d4358c676b37e1d31d4604964cbd89f827b
6
+ metadata.gz: 685a523bf3c3acfd3a6a3117aa38bf058ca7a2dacd2dd22a87c363edcc43f2fdbcb41c291a957f0730512d18f2b2407807dce54f902b6d88996d3bcd2cc943cb
7
+ data.tar.gz: e292dd6152f1889afbbfac79b7b13d046d60dd2398ee067093935db77d059ebc8fd992b080123a9e8a76cd8de506ef5797d2f8cf61b8169e4b6b2c4c7752c62b
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2017-2025 Domizio Demichelis
3
+ Copyright (c) 2017-2026 Domizio Demichelis
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/apps/calendar.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.0.0'
19
+ VERSION = '43.3.0'
20
20
 
21
21
  if VERSION != Pagy::VERSION
22
22
  Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
@@ -68,8 +68,9 @@ class PagyCalendar < Sinatra::Base
68
68
  def pagy_calendar_counts(collection, unit, from, to)
69
69
  # The group_by_period method is provided by the groupdate gem
70
70
  # We use the :skip_counts param for testing the output in cypress
71
+ # If collection is in order: :desc, add the reverse: true option to the next line
71
72
  collection.group_by_period(unit, :time, range: from...to).count.values \
72
- unless params[:skip_counts] == 'true'
73
+ unless params[:skip_counts] == 'true'
73
74
  end
74
75
 
75
76
  # Root route/action
@@ -94,9 +95,8 @@ class PagyCalendar < Sinatra::Base
94
95
  <<~ERB
95
96
  <!DOCTYPE html>
96
97
  <html lang="en">
97
- <html>
98
98
  <head>
99
- <title>Pagy Calendar App</title>
99
+ <title>Pagy Calendar App</title>
100
100
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
101
101
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
102
102
  integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
@@ -104,13 +104,13 @@ class PagyCalendar < Sinatra::Base
104
104
  <style type="text/css">
105
105
  @media screen { html, body {
106
106
  font-size: .8rem;
107
- line-height: 1.1s;
107
+ line-height: 1.1;
108
108
  padding: 0;
109
109
  margin: 0;
110
110
  } }
111
111
  body {
112
112
  background-color: #f7f7f7;
113
- color: #51585F;"
113
+ color: #51585F;
114
114
  font-family: sans-serif;
115
115
  }
116
116
  .content {
@@ -181,7 +181,7 @@ class PagyCalendar < Sinatra::Base
181
181
  </div>
182
182
 
183
183
  <!-- standard pagination of the last unit (month) -->
184
- <p><%= @pagy.series_nav(:bootstrap, id: 'pages-nav', aria_label: 'Pages') if @pagy.last > 1 %><p/>
184
+ <p><%= @pagy.series_nav(:bootstrap, id: 'pages-nav', aria_label: 'Pages') if @pagy.last > 1 %></p>
185
185
  </div>
186
186
  ERB
187
187
  end
@@ -189,15 +189,14 @@ end
189
189
 
190
190
  # ActiveRecord setup
191
191
  require 'active_record'
192
+
192
193
  # Log
193
194
  output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
194
195
  ActiveRecord::Base.logger = Logger.new(output)
195
- # SQLite DB files
196
- dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
197
- abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
198
- unless File.writable?(dir)
196
+
199
197
  # Connection
200
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-calendar.sqlite3")
198
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file:memdb1?mode=memory&cache=shared')
199
+
201
200
  Date.beginning_of_week = :monday # just for rails default compatibiity
202
201
  # Groupdate initializer (https://github.com/ankane/groupdate)
203
202
  # Groupdate week_start default is :sunday, while rails and pagy default to :monday
data/apps/demo.ru CHANGED
@@ -19,7 +19,7 @@
19
19
  # URL
20
20
  # http://127.0.0.1:8000
21
21
 
22
- VERSION = '43.0.0'
22
+ VERSION = '43.3.0'
23
23
 
24
24
  if VERSION != Pagy::VERSION
25
25
  Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
@@ -46,7 +46,7 @@ SECTIONS = { pagy: { css_anchor: 'pagy-css' },
46
46
  require 'sinatra/base'
47
47
 
48
48
  # Pagy init
49
- Pagy.options[:client_max_limit] = 100
49
+ Pagy::OPTIONS[:client_max_limit] = 100
50
50
 
51
51
  # Sinatra application
52
52
  class PagyDemo < Sinatra::Base
@@ -86,7 +86,7 @@ class PagyDemo < Sinatra::Base
86
86
  end
87
87
 
88
88
  PAGY_LIKE_HEAD =
89
- %(#{Pagy.dev_tools if ENV['CY_TEST'] != 'true'}
89
+ %(#{Pagy.dev_tools if ENV['E2E_TEST'] != 'true'}
90
90
  <style>
91
91
  /* black/white backdrop color based on --B */
92
92
  .pagy { background-color: hsl(0 0 calc(100 * var(--B))) !important; }
@@ -476,12 +476,12 @@ class MockCollection < Array
476
476
  end
477
477
 
478
478
  def offset(value)
479
- @collection = self[value..]
479
+ @collection = self[value..] || []
480
480
  self
481
481
  end
482
482
 
483
483
  def limit(value)
484
- @collection[0, value]
484
+ @collection.empty? ? [] : @collection[0, value]
485
485
  end
486
486
 
487
487
  def count(*)
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ################# IMPORTANT WARNING #################
4
+ # This setup forces Pagy to use the Rails `url_for` method,
5
+ # which is significantly slower (~20x) than Pagy's native URL generation.
6
+
7
+ # Use this file ONLY if you absolutely want to support the page param as a dynamic segment.
8
+ # (e.g. get '/comments(/:page)', to: 'comments#index').
9
+ # #####################################################
10
+
11
+ # USAGE
12
+
13
+ # initializers/pagy.rb
14
+ # require Pagy::ROOT.join('apps/enable_rails_page_segment.rb')
15
+
16
+ # config/routes.rb (example)
17
+ # get '/comments(/:page)', to: 'comments#index'
18
+
19
+
20
+ # Use plain Strings tokens instead of Pagy::EscapedValue strings
21
+ Pagy.send(:remove_const, :PAGE_TOKEN) ; Pagy::PAGE_TOKEN = '___PAGY_PAGE___'
22
+ Pagy.send(:remove_const, :LIMIT_TOKEN) ; Pagy::LIMIT_TOKEN = '___PAGY_LIMIT___'
23
+
24
+ # Require the pagy sources to override
25
+ require_relative '../lib/pagy/toolbox/paginators/method'
26
+ require_relative '../lib/pagy/modules/abilities/linkable'
27
+
28
+ class Pagy
29
+ # Switch to the `request.params` to get access to rails-added path parameters
30
+ module RequestOverride
31
+ def get_params(request)
32
+ request.params
33
+ end
34
+ end
35
+ Request.prepend RequestOverride
36
+
37
+ # Inject the caller context into the Pagy instance
38
+ module MethodOverride
39
+ def pagy(...)
40
+ super.tap { _1[0].instance_variable_set(:@context, self) }
41
+ end
42
+ end
43
+ Method.prepend MethodOverride
44
+
45
+ # Compose the final URL using `url_for`.
46
+ module LinkableOverride
47
+ def compose_url(absolute, _path, params, fragment)
48
+ params[:anchor] = fragment if fragment
49
+ params[:only_path] = !absolute
50
+ @context.url_for(params)
51
+ end
52
+ end
53
+ Linkable.prepend LinkableOverride
54
+ end
data/apps/index.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # PagyApp module
3
+ # PagyApps module
4
4
  module PagyApps
5
5
  # Return the hash of app name/path
6
6
  INDEX = Dir[File.expand_path('./*.ru', __dir__)].to_h do |f|
@@ -0,0 +1,316 @@
1
+ # frozen_string_literal: true
2
+
3
+ # DESCRIPTION
4
+ # Showcase the Keynav pagination with independent instances
5
+ #
6
+ # DOC
7
+ # https://ddnexus.github.io/pagy/playground/#keyset-apps
8
+ #
9
+ # BIN HELP
10
+ # pagy -h
11
+ #
12
+ # DEV USAGE
13
+ # pagy clone keynav
14
+ # pagy ./keynav.ru
15
+ #
16
+ # URL
17
+ # http://127.0.0.1:8000
18
+
19
+ VERSION = '43.3.0'
20
+
21
+ if VERSION != Pagy::VERSION
22
+ Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
23
+ end
24
+
25
+ # Bundle
26
+ require 'bundler/inline'
27
+ gemfile(!Pagy::ROOT.join('pagy.gemspec').exist?) do
28
+ source 'https://rubygems.org'
29
+ gem 'activerecord'
30
+ gem 'puma'
31
+ gem 'sinatra'
32
+ gem 'sqlite3'
33
+ end
34
+
35
+ # Sinatra setup
36
+ require 'sinatra/base'
37
+ # Sinatra application
38
+ class PagyKeynav < Sinatra::Base
39
+ include Pagy::Method
40
+
41
+ get('/javascripts/:file') do
42
+ format = params[:file].split('.').last
43
+ if format == 'js'
44
+ content_type 'application/javascript'
45
+ elsif format == 'map'
46
+ content_type 'application/json'
47
+ end
48
+ send_file Pagy::ROOT.join('javascripts', params[:file])
49
+ end
50
+
51
+ # Root route/action
52
+ get '/' do
53
+ Time.zone = 'UTC'
54
+
55
+ @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }.freeze
56
+ @pagy1, @pets1 = pagy(:keynav_js, Pet.order(@order), limit: 4, root_key: 'animal1')
57
+ @ids1 = @pets1.pluck(:id)
58
+ @pagy2, @pets2 = pagy(:keynav_js, Pet.order(@order), limit: 4, root_key: 'animal2')
59
+ @ids2 = @pets2.pluck(:id)
60
+ erb :main
61
+ end
62
+
63
+ helpers do
64
+ def order_symbol(dir)
65
+ { asc: '&#x2197;', desc: '&#x2198;' }[dir]
66
+ end
67
+ end
68
+
69
+ # Views
70
+ template :layout do
71
+ <<~ERB
72
+ <!DOCTYPE html>
73
+ <html lang="en">
74
+ <head>
75
+ <title>Pagy Keynav (root_key) App</title>
76
+ <script src="javascripts/pagy.js"></script>
77
+ <script>
78
+ window.addEventListener("load", Pagy.init);
79
+ </script>
80
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
81
+ <style type="text/css">
82
+ @media screen { html, body {
83
+ font-size: 1rem;
84
+ line-height: 1.2;
85
+ padding: 0;
86
+ margin: 0;
87
+ } }
88
+ body {
89
+ background: white !important;
90
+ margin: 0 !important;
91
+ font-family: sans-serif !important;
92
+ }
93
+ .main-content {
94
+ padding: 1rem 1.5rem 2rem !important;
95
+ }
96
+ #content {
97
+ display: flex; /* Enables Flexbox */
98
+ flex-wrap: wrap; /* Allows stacking */
99
+ gap: 20px; /* Gap between items */
100
+ /* Just for visual clarity of the container boundaries */
101
+ /*padding: 10px;
102
+ background-color: #e0e7ff;
103
+ border-radius: 8px;
104
+ border: 2px dashed #6366f1; */
105
+ }
106
+ .box {
107
+ flex: 1; /* Grow to fill space */
108
+ min-width: 300px; /* Stack if space < 300px */
109
+ /* Visual Styling */
110
+ background-color: white;
111
+ padding: 25px;
112
+ border-radius: 6px;
113
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
114
+ border: 1px solid #ddd;
115
+ }
116
+ .pagy {
117
+ padding: .5em;
118
+ margin: .3em 0;
119
+ width: fit-content;
120
+ box-shadow: 5px 5px 10px 0px rgba(0,0,0,0.2);
121
+ }
122
+ <%= Pagy::ROOT.join('stylesheets/pagy.css').read %>
123
+ </style>
124
+ </head>
125
+ <body>
126
+ <%= yield %>
127
+ </body>
128
+ </html>
129
+ ERB
130
+ end
131
+
132
+ template :main do
133
+ <<~ERB
134
+ <div class="main-content">
135
+ <h1>Pagy Keynav App</h1>
136
+ <p>Self-contained, standalone app usable to easily reproduce any Keynav related pagy issue
137
+ with ActiveRecord sets.</p>
138
+ <p>The panels below show how to use the <code>:root_key</code> option for independent instances in the same request.</p>
139
+
140
+ <p>Notice that Keynav works also with Sequel sets.</p>
141
+
142
+ <h2>Versions</h2>
143
+ <ul>
144
+ <li>Ruby: <%= RUBY_VERSION %></li>
145
+ <li>Rack: <%= Rack::RELEASE %></li>
146
+ <li>Sinatra: <%= Sinatra::VERSION %></li>
147
+ <li>Pagy: <%= Pagy::VERSION %></li>
148
+ </ul>
149
+
150
+ <div id="content">
151
+ <div class="box">
152
+ <h3>Collection 1</h3>
153
+ <p id="records">@ids: <%= @ids1.join(',') %></p>
154
+ <div class="collection">
155
+ <table border="1" style="border-collapse: collapse; border-spacing: 0; padding: 0.2rem;">
156
+ <tr>
157
+ <th scope="col">animal <%= order_symbol(@order[:animal]) %></th>
158
+ <th scope="col">name <%= order_symbol(@order[:name]) %></th>
159
+ <th scope="col">birthdate <%= order_symbol(@order[:birthdate]) %></th>
160
+ <th scope="col">id <%= order_symbol(@order[:id]) %></th>
161
+ </tr>
162
+ <% @pets1.each do |pet| %>
163
+ <tr>
164
+ <td><%= pet.animal %></td>
165
+ <td><%= pet.name %></td>
166
+ <td><%= pet.birthdate %></td>
167
+ <td><%= pet.id %></td>
168
+ </tr>
169
+ <% end %>
170
+ </table>
171
+ </div>
172
+
173
+ <h4>@pagy.series_nav</h4>
174
+ <%= @pagy1.series_nav(id: 'series-nav',
175
+ aria_label: 'Pages (nav)') %>
176
+
177
+ <h4>@pagy.series_nav_js (responsive)</h4>
178
+ <%= @pagy1.series_nav_js(id: 'series-nav-js-responsive',
179
+ aria_label: 'Pages (nav_js_responsive)',
180
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
181
+ <h4>@pagy.input_nav_js</h4>
182
+ <%= @pagy1.input_nav_js(id: 'input-nav-js',
183
+ aria_label: 'Pages (input_nav_js)') %>
184
+
185
+ <h4>@pagy.info_tag</h4>
186
+ <%= @pagy1.info_tag(id: 'pagy-info') %>
187
+ </div>
188
+
189
+ <div class="box">
190
+ <h3>Collection 2</h3>
191
+ <p id="records">@ids: <%= @ids2.join(',') %></p>
192
+ <div class="collection">
193
+ <table border="1" style="border-collapse: collapse; border-spacing: 0; padding: 0.2rem;">
194
+ <tr>
195
+ <th scope="col">animal <%= order_symbol(@order[:animal]) %></th>
196
+ <th scope="col">name <%= order_symbol(@order[:name]) %></th>
197
+ <th scope="col">birthdate <%= order_symbol(@order[:birthdate]) %></th>
198
+ <th scope="col">id <%= order_symbol(@order[:id]) %></th>
199
+ </tr>
200
+ <% @pets2.each do |pet| %>
201
+ <tr>
202
+ <td><%= pet.animal %></td>
203
+ <td><%= pet.name %></td>
204
+ <td><%= pet.birthdate %></td>
205
+ <td><%= pet.id %></td>
206
+ </tr>
207
+ <% end %>
208
+ </table>
209
+ </div>
210
+
211
+ <h4>@pagy.series_nav</h4>
212
+ <%= @pagy2.series_nav(id: 'series-nav',
213
+ aria_label: 'Pages (nav)') %>
214
+
215
+ <h4>@pagy.series_nav_js (responsive)</h4>
216
+ <%= @pagy2.series_nav_js(id: 'series-nav-js-responsive',
217
+ aria_label: 'Pages (nav_js_responsive)',
218
+ steps: { 0 => 5, 500 => 7, 750 => 9, 1000 => 11 }) %>
219
+ <h4>@pagy.input_nav_js</h4>
220
+ <%= @pagy2.input_nav_js(id: 'input-nav-js',
221
+ aria_label: 'Pages (input_nav_js)') %>
222
+
223
+ <h4>@pagy.info_tag</h4>
224
+ <%= @pagy2.info_tag(id: 'pagy-info') %>
225
+ </div>
226
+ </div>
227
+ </div>
228
+ ERB
229
+ end
230
+ end
231
+
232
+ # ActiveRecord setup
233
+ require 'active_record'
234
+
235
+ # Match the microsecods with the strings stored into the time columns of SQLite
236
+ # ActiveSupport::JSON::Encoding.time_precision = 6
237
+
238
+ # Log
239
+ output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
240
+ ActiveRecord::Base.logger = Logger.new(output)
241
+ # Connection
242
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file:memdb1?mode=memory&cache=shared')
243
+ # Schema
244
+ ActiveRecord::Schema.define do
245
+ create_table :pets, force: true do |t|
246
+ t.string :animal
247
+ t.string :name
248
+ t.date :birthdate
249
+ end
250
+ end
251
+
252
+ # Models
253
+ class Pet < ActiveRecord::Base; end
254
+
255
+ data = <<~DATA
256
+ Luna | dog | 2018-03-10
257
+ Coco | cat | 2019-05-15
258
+ Dodo | dog | 2020-06-25
259
+ Wiki | bird | 2018-03-12
260
+ Baby | rabbit | 2020-01-13
261
+ Neki | horse | 2021-07-20
262
+ Tino | donkey | 2019-06-18
263
+ Plot | cat | 2022-09-21
264
+ Riki | cat | 2018-09-14
265
+ Susi | horse | 2018-10-26
266
+ Coco | pig | 2020-08-29
267
+ Momo | bird | 2023-08-25
268
+ Lili | cat | 2021-07-22
269
+ Beli | pig | 2020-07-26
270
+ Rocky | bird | 2022-08-19
271
+ Vyvy | dog | 2018-05-16
272
+ Susi | horse | 2024-01-25
273
+ Ella | cat | 2020-02-20
274
+ Rocky | dog | 2019-09-19
275
+ Juni | rabbit | 2020-08-24
276
+ Coco | bird | 2021-03-17
277
+ Susi | dog | 2021-07-28
278
+ Luna | horse | 2023-05-14
279
+ Gigi | pig | 2022-05-19
280
+ Coco | cat | 2020-02-20
281
+ Nino | donkey | 2019-06-17
282
+ Luna | cat | 2022-02-09
283
+ Popi | dog | 2020-09-26
284
+ Lili | pig | 2022-06-18
285
+ Mina | horse | 2021-04-21
286
+ Susi | rabbit | 2023-05-18
287
+ Toni | donkey | 2018-06-22
288
+ Rocky | horse | 2019-09-28
289
+ Lili | cat | 2019-03-18
290
+ Roby | cat | 2022-06-19
291
+ Anto | horse | 2022-08-18
292
+ Susi | pig | 2021-04-21
293
+ Boly | bird | 2020-03-29
294
+ Sky | cat | 2023-07-19
295
+ Lili | dog | 2020-01-28
296
+ Fami | snake | 2023-04-27
297
+ Lopi | pig | 2019-06-19
298
+ Rocky | snake | 2022-03-13
299
+ Denis | dog | 2022-06-19
300
+ Maca | cat | 2022-06-19
301
+ Luna | dog | 2022-08-15
302
+ Jeme | horse | 2019-08-08
303
+ Sary | bird | 2023-04-29
304
+ Rocky | bird | 2023-05-14
305
+ Coco | dog | 2023-05-27
306
+ DATA
307
+
308
+ # DB seed
309
+ pets = []
310
+ data.each_line(chomp: true) do |pet|
311
+ name, animal, birthdate = pet.split('|').map(&:strip)
312
+ pets << { name:, animal:, birthdate: }
313
+ end
314
+ Pet.insert_all(pets)
315
+
316
+ run PagyKeynav
data/apps/keynav.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.0.0'
19
+ VERSION = '43.3.0'
20
20
 
21
21
  if VERSION != Pagy::VERSION
22
22
  Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
@@ -52,8 +52,10 @@ class PagyKeynav < Sinatra::Base
52
52
  get '/' do
53
53
  Time.zone = 'UTC'
54
54
 
55
- @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }
55
+ @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }.freeze
56
56
  @pagy, @pets = pagy(:keynav_js, Pet.order(@order), limit: 4, client_max_limit: 100)
57
+ # Support also root_key for replacing url in javascript
58
+ # @pagy, @pets = pagy(:keynav_js, Pet.order(@order), limit: 4, client_max_limit: 100, root_key: 'animal')
57
59
  @ids = @pets.pluck(:id)
58
60
  erb :main
59
61
  end
@@ -69,18 +71,17 @@ class PagyKeynav < Sinatra::Base
69
71
  <<~ERB
70
72
  <!DOCTYPE html>
71
73
  <html lang="en">
72
- <html>
73
74
  <head>
74
- <title>Pagy Keynav App</title>
75
+ <title>Pagy Keynav App</title>
75
76
  <script src="javascripts/pagy.js"></script>
76
- <script>
77
+ <script>
77
78
  window.addEventListener("load", Pagy.init);
78
79
  </script>
79
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
80
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
80
81
  <style type="text/css">
81
82
  @media screen { html, body {
82
83
  font-size: 1rem;
83
- line-height: 1.2s;
84
+ line-height: 1.2;
84
85
  padding: 0;
85
86
  margin: 0;
86
87
  } }
@@ -92,7 +93,7 @@ class PagyKeynav < Sinatra::Base
92
93
  .main-content {
93
94
  padding: 1rem 1.5rem 2rem !important;
94
95
  }
95
- .pagy {
96
+ .pagy {
96
97
  padding: .5em;
97
98
  margin: .3em 0;
98
99
  width: fit-content;
@@ -176,12 +177,8 @@ require 'active_record'
176
177
  # Log
177
178
  output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
178
179
  ActiveRecord::Base.logger = Logger.new(output)
179
- # SQLite DB files
180
- dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
181
- abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
182
- unless File.writable?(dir)
183
180
  # Connection
184
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-keyset-ar.sqlite3")
181
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file:memdb1?mode=memory&cache=shared')
185
182
  # Schema
186
183
  ActiveRecord::Schema.define do
187
184
  create_table :pets, force: true do |t|
data/apps/keyset.ru CHANGED
@@ -16,7 +16,7 @@
16
16
  # URL
17
17
  # http://127.0.0.1:8000
18
18
 
19
- VERSION = '43.0.0'
19
+ VERSION = '43.3.0'
20
20
 
21
21
  if VERSION != Pagy::VERSION
22
22
  Warning.warn("\n>>> WARNING! '#{File.basename(__FILE__)}-#{VERSION}' running with 'pagy-#{Pagy::VERSION}'! <<< \n\n")
@@ -42,7 +42,7 @@ class PagyKeyset < Sinatra::Base
42
42
  get '/' do
43
43
  Time.zone = 'UTC'
44
44
 
45
- @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }
45
+ @order = { animal: :asc, name: :asc, birthdate: :desc, id: :asc }.freeze
46
46
  @pagy, @pets = pagy(:keyset, Pet.order(@order), limit: 10, client_max_limit: 100)
47
47
  # response.headers.merge!(@pagy.headers_hash)
48
48
  erb :main
@@ -59,14 +59,13 @@ class PagyKeyset < Sinatra::Base
59
59
  <<~ERB
60
60
  <!DOCTYPE html>
61
61
  <html lang="en">
62
- <html>
63
62
  <head>
64
- <title>Pagy Keyset App</title>
63
+ <title>Pagy Keyset App</title>
65
64
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
65
  <style type="text/css">
67
66
  @media screen { html, body {
68
67
  font-size: 1rem;
69
- line-height: 1.2s;
68
+ line-height: 1.2;
70
69
  padding: 0;
71
70
  margin: 0;
72
71
  } }
@@ -122,7 +121,6 @@ class PagyKeyset < Sinatra::Base
122
121
  <% end %>
123
122
  </table>
124
123
  </div>
125
- <p>
126
124
  <nav class="pagy" id="next" aria-label="Pagy next">
127
125
  <%= @pagy.next_tag(text: 'Next page &gt;') %>
128
126
  </nav>
@@ -140,12 +138,8 @@ require 'active_record'
140
138
  # Log
141
139
  output = ENV['APP_ENV'].equal?('showcase') ? IO::NULL : $stdout
142
140
  ActiveRecord::Base.logger = Logger.new(output)
143
- # SQLite DB files
144
- dir = ENV['APP_ENV'].equal?('development') ? '.' : Dir.pwd # app dir in dev or pwd otherwise
145
- abort "ERROR: Cannot create DB files: the directory #{dir.inspect} is not writable." \
146
- unless File.writable?(dir)
147
141
  # Connection
148
- ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-keyset-ar.sqlite3")
142
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'file:memdb1?mode=memory&cache=shared')
149
143
  # Schema
150
144
  ActiveRecord::Schema.define do
151
145
  create_table :pets, force: true do |t|