pagy 7.0.11 → 8.0.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/apps/calendar.ru +2196 -0
  3. data/lib/apps/demo.ru +452 -0
  4. data/lib/apps/rails.ru +205 -0
  5. data/lib/apps/repro.ru +168 -0
  6. data/lib/bin/pagy +83 -0
  7. data/lib/config/pagy.rb +6 -17
  8. data/lib/javascripts/pagy-dev.js +10 -10
  9. data/lib/javascripts/pagy-module.js +9 -9
  10. data/lib/javascripts/pagy.js +1 -1
  11. data/lib/locales/ar.yml +2 -2
  12. data/lib/locales/be.yml +4 -4
  13. data/lib/locales/bg.yml +4 -4
  14. data/lib/locales/bs.yml +4 -4
  15. data/lib/locales/ca.yml +4 -4
  16. data/lib/locales/ckb.yml +4 -4
  17. data/lib/locales/cs.yml +4 -4
  18. data/lib/locales/da.yml +4 -4
  19. data/lib/locales/de.yml +4 -4
  20. data/lib/locales/en.yml +4 -4
  21. data/lib/locales/es.yml +2 -2
  22. data/lib/locales/fr.yml +4 -4
  23. data/lib/locales/hr.yml +4 -4
  24. data/lib/locales/id.yml +4 -4
  25. data/lib/locales/it.yml +4 -4
  26. data/lib/locales/ja.yml +4 -4
  27. data/lib/locales/km.yml +4 -4
  28. data/lib/locales/ko.yml +4 -4
  29. data/lib/locales/nb.yml +4 -4
  30. data/lib/locales/nl.yml +4 -4
  31. data/lib/locales/nn.yml +4 -4
  32. data/lib/locales/pl.yml +4 -4
  33. data/lib/locales/pt-BR.yml +2 -2
  34. data/lib/locales/pt.yml +2 -2
  35. data/lib/locales/ru.yml +4 -4
  36. data/lib/locales/sr.yml +4 -4
  37. data/lib/locales/sv-SE.yml +4 -4
  38. data/lib/locales/sv.yml +4 -4
  39. data/lib/locales/sw.yml +4 -4
  40. data/lib/locales/ta.yml +4 -4
  41. data/lib/locales/tr.yml +4 -4
  42. data/lib/locales/uk.yml +4 -4
  43. data/lib/locales/vi.yml +4 -4
  44. data/lib/locales/zh-CN.yml +4 -4
  45. data/lib/locales/zh-HK.yml +4 -4
  46. data/lib/locales/zh-TW.yml +4 -4
  47. data/lib/optimist.rb +1022 -0
  48. data/lib/pagy/extras/bootstrap.rb +52 -63
  49. data/lib/pagy/extras/bulma.rb +48 -64
  50. data/lib/pagy/extras/foundation.rb +49 -61
  51. data/lib/pagy/extras/items.rb +21 -18
  52. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +1 -1
  53. data/lib/pagy/extras/materialize.rb +52 -51
  54. data/lib/pagy/extras/pagy.rb +82 -0
  55. data/lib/pagy/extras/semantic.rb +46 -50
  56. data/lib/pagy/extras/trim.rb +12 -12
  57. data/lib/pagy/extras/uikit.rb +48 -49
  58. data/lib/pagy/frontend.rb +31 -48
  59. data/lib/pagy/url_helpers.rb +1 -2
  60. data/lib/pagy.rb +10 -9
  61. data/lib/stylesheets/pagy.css +19 -34
  62. data/lib/stylesheets/pagy.scss +17 -19
  63. data/lib/stylesheets/pagy.tailwind.css +21 -0
  64. metadata +25 -9
  65. data/lib/pagy/extras/navs.rb +0 -51
  66. data/lib/pagy/extras/support.rb +0 -40
  67. data/lib/stylesheets/pagy.tailwind.scss +0 -24
data/lib/apps/demo.ru ADDED
@@ -0,0 +1,452 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Interactive showcase for all the pagy helpers and CSS styles
4
+
5
+ # DEMO USAGE
6
+ # pagy demo
7
+
8
+ # DEV USAGE
9
+ # pagy clone demo
10
+ # pagy ./demo.ru
11
+
12
+ # URL
13
+ # http://0.0.0.0:8000
14
+
15
+ # HELP
16
+ # pagy -h
17
+
18
+ # DOC
19
+ # https://ddnexus.github.io/pagy/playground/#3-demo-app
20
+
21
+ VERSION = '8.0.0'
22
+
23
+ require 'bundler/inline'
24
+ gemfile(true) do
25
+ source 'https://rubygems.org'
26
+ gem 'oj'
27
+ gem 'puma'
28
+ gem 'rouge'
29
+ gem 'sinatra'
30
+ gem 'sinatra-contrib'
31
+ end
32
+
33
+ # pagy initializer
34
+ STYLES = { pagy: { extra: 'pagy', prefix: '', css_anchor: 'pagy-scss' },
35
+ bootstrap: {},
36
+ bulma: {},
37
+ foundation: {},
38
+ materialize: {},
39
+ semantic: {},
40
+ tailwind: { extra: 'pagy', prefix: '', css_anchor: 'pagy-tailwind-css' },
41
+ uikit: {} }.freeze
42
+
43
+ STYLES.each_key do |style|
44
+ require "pagy/extras/#{STYLES[style][:extra] || style}"
45
+ end
46
+ require 'pagy/extras/items'
47
+ require 'pagy/extras/trim'
48
+ Pagy::DEFAULT[:trim_extra] = false # opt-in trim
49
+ Pagy::DEFAULT[:size] = [1, 4, 4, 1] # old size default
50
+
51
+ # sinatra setup
52
+ require 'sinatra/base'
53
+
54
+ # sinatra application
55
+ class PagyDemo < Sinatra::Base
56
+ configure do
57
+ enable :inline_templates
58
+ end
59
+
60
+ include Pagy::Backend
61
+
62
+ get '/' do
63
+ redirect '/pagy'
64
+ end
65
+
66
+ get '/template' do
67
+ collection = MockCollection.new
68
+ @pagy, @records = pagy(collection, trim_extra: params['trim'])
69
+
70
+ erb :template, locals: { pagy: @pagy, style: 'pagy' }
71
+ end
72
+
73
+ get('/javascripts/:file') do
74
+ content_type 'application/javascript'
75
+ send_file Pagy.root.join('javascripts', params[:file])
76
+ end
77
+
78
+ get('/stylesheets/:file') do
79
+ content_type 'text/css'
80
+ send_file Pagy.root.join('stylesheets', params[:file])
81
+ end
82
+
83
+ # one route/action per style
84
+ STYLES.each_key do |style|
85
+ prefix = STYLES[style][:prefix] || "_#{style}"
86
+
87
+ get("/#{style}/?:trim?") do
88
+ collection = MockCollection.new
89
+ @pagy, @records = pagy(collection, trim_extra: params['trim'])
90
+
91
+ erb :helpers, locals: { style:, prefix: }
92
+ end
93
+ end
94
+
95
+ helpers do
96
+ include Pagy::Frontend
97
+
98
+ def style_menu
99
+ html = +%(<div id="style-menu"> )
100
+ STYLES.each_key { |style| html << %(<a href="/#{style}">#{style}</a>) }
101
+ html << %(<a href="/template">template</a>)
102
+ html << %(</div>)
103
+ end
104
+
105
+ def highlight(html, format: :html)
106
+ if format == :html
107
+ html = html.gsub(/>[\s]*</, '><').strip # template single line no spaces around/between tags
108
+ html = Formatter.new.format(html)
109
+ end
110
+ lexer = Rouge::Lexers::ERB.new
111
+ formatter = Rouge::Formatters::HTMLInline.new('monokai.sublime')
112
+ summary = { html: 'Served HTML (pretty formatted)', erb: 'ERB Template' }
113
+ %(<details><summary>#{summary[format]}</summary><pre>\n#{
114
+ formatter.format(lexer.lex(html))
115
+ }</pre></details>)
116
+ end
117
+ end
118
+ end
119
+
120
+ # Cheap pagy formatter for helpers output
121
+ class Formatter
122
+ INDENT = ' '
123
+ TEXT_SPACE = "\u00B7"
124
+ TEXT = /^([^<>]+)(.*)/
125
+ UNPAIRED = /^(<(input|link).*?>)(.*)/
126
+ PAIRED = %r{^(<(head|nav|div|span|p|a|b|label|ul|li).*?>)(.*?)(</\2>)(.*)}
127
+ WRAPPER = /<.*?>/
128
+ DATA_PAGY = /(data-pagy="([^"]+)")/
129
+
130
+ def initialize
131
+ @formatted = +''
132
+ end
133
+
134
+ def format(input, level = 0)
135
+ process(input, level)
136
+ @formatted
137
+ end
138
+
139
+ private
140
+
141
+ def process(input, level)
142
+ push = ->(content) { @formatted << ((INDENT * level) << content << "\n") }
143
+ rest = nil
144
+ if (match = input.match(TEXT))
145
+ text, rest = match.captures
146
+ push.(text.gsub(' ', TEXT_SPACE))
147
+ elsif (match = input.match(UNPAIRED))
148
+ tag, _name, rest = match.captures
149
+ push.(tag)
150
+ elsif (match = input.match(PAIRED))
151
+ tag_start, name, block, tag_end, rest = match.captures
152
+ ## Handle incomplete same-tag nesting
153
+ while block.scan(/<#{name}.*?>/).size > block.scan(tag_end).size
154
+ more, rest = rest.split(tag_end, 2)
155
+ block << tag_end << more
156
+ end
157
+ if (match = tag_start.match(DATA_PAGY))
158
+ search, data = match.captures
159
+ formatted = data.scan(/.{1,76}/).join("\n")
160
+ replace = %(\n#{INDENT * (level + 1)}data-pagy="#{formatted}")
161
+ tag_start.sub!(search, replace)
162
+ end
163
+ if block.match(WRAPPER)
164
+ push.(tag_start)
165
+ process(block, level + 1)
166
+ push.(tag_end)
167
+ else
168
+ push.(tag_start << block << tag_end)
169
+ end
170
+ end
171
+ process(rest, level) if rest
172
+ end
173
+ end
174
+
175
+ # Simple array-based collection that acts as a standard DB collection.
176
+ class MockCollection < Array
177
+ def initialize(arr = Array(1..1000))
178
+ super
179
+ @collection = clone
180
+ end
181
+
182
+ def offset(value)
183
+ @collection = self[value..]
184
+ self
185
+ end
186
+
187
+ def limit(value)
188
+ @collection[0, value]
189
+ end
190
+
191
+ def count(*)
192
+ size
193
+ end
194
+ end
195
+
196
+ run PagyDemo
197
+
198
+ # We store the template in a constant instead of writing it inline, so we can highlight it more easily
199
+ TEMPLATE = <<~ERB
200
+ <%# IMPORTANT: use '<%== ... ' instead of '<%= ... ' if you run this in rails %>
201
+
202
+ <%# The a variable below is set to a lambda that generates the a tag %>
203
+ <%# Usage: a_tag = a.(page_number, text, classes: nil, aria_label: nil) %>
204
+ <% a = pagy_anchor(pagy) %>
205
+ <nav class="pagy nav" aria-label="Pages">
206
+ <%# Previous page link %>
207
+ <% if pagy.prev %>
208
+ <%= a.(pagy.prev, '&lt;', aria_label: 'Previous') %>
209
+ <% else %>
210
+ <a role="link" aria-disabled="true" aria-label="Previous">&lt;</a>
211
+ <% end %>
212
+ <%# Page links (series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]) %>
213
+ <% pagy.series.each do |item| %>
214
+ <% if item.is_a?(Integer) %>
215
+ <%= a.(item) %>
216
+ <% elsif item.is_a?(String) %>
217
+ <a role="link" aria-disabled="true" aria-current="page" class="current"><%= item %></a>
218
+ <% elsif item == :gap %>
219
+ <a role="link" aria-disabled="true" class="gap">&hellip;</a>
220
+ <% end %>
221
+ <% end %>
222
+ <%# Next page link %>
223
+ <% if pagy.next %>
224
+ <%= a.(pagy.next, '&gt;', aria_label: 'Next') %>
225
+ <% else %>
226
+ <a role="link" aria-disabled="true" aria-label="Next">&lt;</a>
227
+ <% end %>
228
+ </nav>
229
+ ERB
230
+
231
+ __END__
232
+
233
+ @@ layout
234
+ <!DOCTYPE html>
235
+ <html lang="en">
236
+ <head>
237
+ <title>Pagy Demo App</title>
238
+ <script src="<%= %(/javascripts/#{"pagy#{'-dev' if ENV['DEBUG']}.js"}) %>"></script>
239
+ <script>
240
+ window.addEventListener("load", Pagy.init);
241
+ </script>
242
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
243
+ <%= erb :"#{style}_head" if defined?(style) %>
244
+ <style type="text/css">
245
+ @media screen { html, body {
246
+ font-size: 1rem;
247
+ line-heigth: 1.2s;
248
+ padding: 0;
249
+ margin: 0;
250
+ } }
251
+ body {
252
+ background: white !important;
253
+ margin: 0 !important;
254
+ font-family: sans-serif !important;
255
+ }
256
+ h1, h4 {
257
+ font-size: 1.8rem !important;
258
+ font-weight: 600 !important;
259
+ margin-top: 1rem !important;
260
+ margin-bottom: 0.7rem !important;
261
+ line-height: 1.5 !important;
262
+ color: rgb(90 90 90) !important;
263
+ }
264
+ h4 {
265
+ font-family: monospace;
266
+ font-size: .9rem !important;
267
+ margin-top: 1.6rem !important;
268
+ }
269
+ summary, .notes {
270
+ font-size: .8rem;
271
+ color: gray;
272
+ margin-top: .6rem;
273
+ font-style: italic;
274
+ cursor: pointer;
275
+ }
276
+ .notes {
277
+ font-family: sans-serif;
278
+ font-weight: normal;
279
+ }
280
+ .notes code{
281
+ background-color: #E8E8E8;
282
+ padding: 0 0.3rem;
283
+ font-style: normal;
284
+ border-radius: 3px;
285
+ }
286
+ .description {
287
+ margin: 1rem 0;
288
+ }
289
+ .description a {
290
+ color: blue;
291
+ text-decoration: underline;
292
+ }
293
+ pre, pre code {
294
+ display: block;
295
+ margin-top: .3rem;
296
+ margin-bottom: 1rem;
297
+ font-size: .8rem !important;
298
+ line-heigth: 1rem !important;
299
+ color: white;
300
+ background-color: rgb(30 30 30);
301
+ padding: 1rem;
302
+ overflow: auto;
303
+ }
304
+ .content {
305
+ padding: 0 1.5rem 2rem !important;
306
+ }
307
+
308
+ #style-menu {
309
+ flex;
310
+ font-family: sans-serif;
311
+ font-size: 1.1rem;
312
+ line-height: 1.5rem;
313
+ white-space: nowrap;
314
+ color: white;
315
+ background-color: gray;
316
+ padding: .2rem 1.5rem;
317
+ }
318
+ #style-menu > :not([hidden]) ~ :not([hidden]) {
319
+ --space-reverse: 0;
320
+ margin-right: calc(0.5rem * var(--space-reverse));
321
+ margin-left: calc(0.5rem * calc(1 - var(--space-reverse)));
322
+ }
323
+ #style-menu a {
324
+ color: inherit;
325
+ text-decoration: none;
326
+ }
327
+ /* Quick demo for overriding the element style attribute of certain pagy helpers
328
+ .pagy input[style] {
329
+ width: 5rem !important;
330
+ }
331
+ */
332
+ </style>
333
+ </head>
334
+ <body>
335
+ <!-- each different class used by each style -->
336
+ <%= style_menu %>
337
+ <div class="content">
338
+ <%= yield %>
339
+ </div>
340
+ </body>
341
+ </html>
342
+
343
+
344
+ @@ pagy_head
345
+ <!-- copy and paste the pagy style in order to edit it -->
346
+ <link rel="stylesheet" href="/stylesheets/pagy.css">
347
+
348
+ @@ bootstrap_head
349
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
350
+
351
+ @@ bulma_head
352
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
353
+
354
+ @@ foundation_head
355
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/foundation-sites@6.8.1/dist/css/foundation.min.css" crossorigin="anonymous">
356
+
357
+ @@ materialize_head
358
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
359
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
360
+
361
+ @@ semantic_head
362
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.css"><script
363
+ src="https://code.jquery.com/jquery-3.1.1.min.js"
364
+ integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
365
+ crossorigin="anonymous"></script>
366
+ <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.5.0/dist/semantic.min.js"></script>
367
+
368
+ @@ tailwind_head
369
+ <script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio"></script>
370
+ <!-- copy and paste the pagy.tailwind style in order to edit it -->
371
+ <style type="text/tailwindcss">
372
+ <%= Pagy.root.join('stylesheets', 'pagy.tailwind.css').read %>
373
+ </style>
374
+
375
+ @@ uikit_head
376
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.18.3/dist/css/uikit.min.css" />
377
+ <script src="https://cdn.jsdelivr.net/npm/uikit@3.18.3/dist/js/uikit.min.js"></script>
378
+ <script src="https://cdn.jsdelivr.net/npm/uikit@3.18.3/dist/js/uikit-icons.min.js"></script>
379
+
380
+
381
+ @@ helpers
382
+ <h1><%= style %></h1>
383
+ <% extra = STYLES[style][:extra] || "#{style}" %>
384
+ <% css_anchor = STYLES[style][:css_anchor] %>
385
+
386
+ <p class="description">See the <a href="http://ddnexus.github.io/pagy/docs/extras/<%= extra %>" target="blank"><%= extra %> extra</a>
387
+ documentation
388
+ <% if css_anchor %>
389
+ and the <a href="http://ddnexus.github.io/pagy/docs/api/stylesheets/#<%= css_anchor %>" target="blank"><%= css_anchor.gsub('-', '.') %></a>
390
+ <% end %>
391
+ for details</p>
392
+
393
+ <h4>Collection</h4>
394
+ <p>@records: <%= @records.join(',') %></p>
395
+
396
+ <h4>pagy<%= prefix %>_nav <span class="notes">Simple nav <code>size: 5</code></span></h4>
397
+ <%= html = send(:"pagy#{prefix}_nav", @pagy, id: 'nav', aria_label: 'Pages nav', size: 5) %>
398
+ <%= highlight(html) %>
399
+
400
+ <h4>pagy<%= prefix %>_nav <span class="notes">Classic nav <code>size: [1,4,4,1]</code></span></h4>
401
+ <%= html = send(:"pagy#{prefix}_nav", @pagy, id: 'nav', aria_label: 'Pages nav') %>
402
+ <%= highlight(html) %>
403
+
404
+ <h4>pagy<%= prefix %>_nav_js <span class="notes">Classic nav <code>size: [1,4,4,1]</code></span></h4>
405
+ <%= html = send(:"pagy#{prefix}_nav_js", @pagy, id: 'nav-js', aria_label: 'Pages nav_js') %>
406
+ <%= highlight(html) %>
407
+
408
+ <h4>pagy<%= prefix %>_nav_js <span class="notes">Responsive <code>steps: {...}</code> (Resize the window to see)</span></h4>
409
+ <%= html = send(:"pagy#{prefix}_nav_js", @pagy, id: 'nav-js-responsive',
410
+ aria_label: 'Pages nav_js_responsive',
411
+ steps: { 0 => 5, 500 => [1,3,3,1], 700 => [1,4,4,1], 900 => [2,4,4,2] }) %>
412
+ <%= highlight(html) %>
413
+
414
+ <h4>pagy<%= prefix %>_combo_nav_js</h4>
415
+ <%= html = send(:"pagy#{prefix}_combo_nav_js", @pagy, id: 'combo-nav-js', aria_label: 'Pages combo_nav_js') %>
416
+ <%= highlight(html) %>
417
+
418
+ <h4>pagy_info</h4>
419
+ <%= html = pagy_info(@pagy, id: 'pagy-info') %>
420
+ <%= highlight(html) %>
421
+
422
+ <% if style.match(/pagy|tailwind/) %>
423
+ <h4>pagy_items_selector_js</h4>
424
+ <%= html = pagy_items_selector_js(@pagy, id: 'items-selector-js') %>
425
+ <%= highlight(html) %>
426
+
427
+ <h4>pagy_prev_a / pagy_next_a</h4>
428
+ <%= html = '<nav class="pagy">' << pagy_prev_a(@pagy) << pagy_next_a(@pagy) << '</nav>' %>
429
+ <%= highlight(html) %>
430
+
431
+ <h4>pagy_prev_link / pagy_next_link <span class="notes">Link not rendered<span></h4>
432
+ <% html = '<head>' << (pagy_prev_link(@pagy)||'') << (pagy_next_link(@pagy)||'') << '</head>' %>
433
+ <%= highlight(html) %>
434
+ <% end %>
435
+
436
+
437
+ @@ template
438
+ <h1>Pagy Template Demo</h1>
439
+
440
+ <p class="description">
441
+ See the <a href="https://ddnexus.github.io/pagy/docs/how-to/#using-your-pagination-templates">
442
+ Custom Templates</a> documentation.
443
+ </p>
444
+ <h4>Collection</h4>
445
+ <p>@records: <%= @records.join(',') %></p>
446
+
447
+ <h4>Rendered ERB template</h4>
448
+
449
+ <%# We don't inline the template here, so we can highlight it more easily %>
450
+ <%= html = ERB.new(TEMPLATE).result(binding) %>
451
+ <%= highlight(TEMPLATE, format: :erb) %>
452
+ <%= highlight(html) %>
data/lib/apps/rails.ru ADDED
@@ -0,0 +1,205 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Starting point to reproduce rails related pagy issues
4
+
5
+ # DEV USAGE
6
+ # pagy clone rails
7
+ # pagy ./rails.ru
8
+
9
+ # URL
10
+ # http://0.0.0.0:8000
11
+
12
+ # HELP
13
+ # pagy -h
14
+
15
+ # DOC
16
+ # https://ddnexus.github.io/pagy/playground/#2-rails-app
17
+
18
+ VERSION = '8.0.0'
19
+
20
+ # Gemfile
21
+ require 'bundler/inline'
22
+ gemfile(true) do
23
+ source 'https://rubygems.org'
24
+ gem 'oj'
25
+ gem 'puma'
26
+ gem 'rails', '~> 7.1'
27
+ gem 'sqlite3'
28
+ end
29
+
30
+ # Pagy initializer
31
+ require 'pagy/extras/pagy'
32
+ require 'pagy/extras/items'
33
+ require 'pagy/extras/overflow'
34
+ Pagy::DEFAULT[:size] = [1, 4, 4, 1]
35
+ Pagy::DEFAULT[:items] = 10
36
+ Pagy::DEFAULT[:overflow] = :empty_page
37
+ Pagy::DEFAULT.freeze
38
+
39
+ # require 'rails/all' # too much stuff
40
+ require 'action_controller/railtie'
41
+ require 'active_record'
42
+
43
+ OUTPUT = Rails.env.showcase? ? IO::NULL : $stdout
44
+
45
+ # Rails config
46
+ class PagyRails < Rails::Application # :nodoc:
47
+ config.root = __dir__
48
+ config.session_store :cookie_store, key: 'cookie_store_key'
49
+ Rails.application.credentials.secret_key_base = 'absolute_secret'
50
+
51
+ config.logger = Logger.new(OUTPUT)
52
+ Rails.logger = config.logger
53
+
54
+ routes.draw do
55
+ root to: 'comments#index'
56
+ get '/javascript' => 'pagy#javascript'
57
+ end
58
+ end
59
+
60
+ # AR config
61
+ dir = Rails.env.development? ? '.' : Dir.pwd # app dir in dev or pwd otherwise
62
+ unless File.writable?(dir)
63
+ warn "ERROR: directory #{dir.inspect} is not writable (the pagy-rails-app needs to create DB files)"
64
+ exit 1
65
+ end
66
+
67
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "#{dir}/tmp/pagy-rails.sqlite3")
68
+ ActiveRecord::Schema.define do
69
+ create_table :posts, force: true do |t|
70
+ t.string :title
71
+ end
72
+
73
+ create_table :comments, force: true do |t|
74
+ t.string :body
75
+ t.integer :post_id
76
+ end
77
+ end
78
+
79
+ # Models
80
+ class Post < ActiveRecord::Base # :nodoc:
81
+ has_many :comments
82
+ end # :nodoc:
83
+
84
+ class Comment < ActiveRecord::Base # :nodoc:
85
+ belongs_to :post
86
+ end # :nodoc:
87
+
88
+ # DB seed
89
+ 1.upto(11) do |pi|
90
+ Post.create(title: "Post #{pi + 1}")
91
+ end
92
+ Post.all.each_with_index do |post, pi|
93
+ 2.times { |ci| Comment.create(post:, body: "Comment #{ci + 1} to Post #{pi + 1}") }
94
+ end
95
+
96
+ # Down here to avoid logging the DB seed above at each restart
97
+ ActiveRecord::Base.logger = Logger.new(OUTPUT)
98
+
99
+ # Helpers
100
+ module CommentsHelper
101
+ include Pagy::Frontend
102
+ end
103
+
104
+ # Controllers
105
+ class CommentsController < ActionController::Base # :nodoc:
106
+ include Rails.application.routes.url_helpers
107
+ include Pagy::Backend
108
+
109
+ def index
110
+ @pagy, @comments = pagy(Comment.all)
111
+ render inline: TEMPLATE
112
+ end
113
+ end
114
+
115
+ # You don't need this in real rails apps (see https://ddnexus.github.io/pagy/docs/api/javascript/setup/#2-configure)
116
+ class PagyController < ActionController::Base
117
+ def javascript
118
+ file = "pagy#{'-dev' if ENV['DEBUG']}.js"
119
+ render js: Pagy.root.join('javascripts', file).read
120
+ end
121
+ end
122
+
123
+ run PagyRails
124
+
125
+ TEMPLATE = <<~ERB
126
+ <!DOCTYPE html>
127
+ <html lang="en">
128
+ <html>
129
+ <head>
130
+ <script src="/javascript"></script>
131
+ <script type="application/javascript">
132
+ window.addEventListener("load", Pagy.init);
133
+ </script>
134
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
135
+ <style type="text/css">
136
+ @media screen { html, body {
137
+ font-size: 1rem;
138
+ line-heigth: 1.2s;
139
+ padding: 0;
140
+ margin: 0;
141
+ } }
142
+ body {
143
+ background: white !important;
144
+ margin: 0 !important;
145
+ font-family: sans-serif !important;
146
+ }
147
+ .content {
148
+ padding: 1rem 1.5rem 2rem !important;
149
+ }
150
+
151
+ /* Quick demo for overriding the element style attribute of certain pagy helpers
152
+ .pagy input[style] {
153
+ width: 5rem !important;
154
+ }
155
+ */
156
+
157
+ /*
158
+ If you want to customize the style,
159
+ please replace the line below with the actual file content
160
+ */
161
+ <%== Pagy.root.join('stylesheets', 'pagy.css').read %>
162
+ </style>
163
+ </head>
164
+
165
+ <body>
166
+
167
+ <div class="content">
168
+ <h3>Pagy Rails App</h3>
169
+ <p> Self-contained, standalone Rails app usable to easily reproduce any rails related pagy issue.</p>
170
+ <p>Please, report the following versions in any new issue.</p>
171
+ <h4>Versions</h4>
172
+ <ul>
173
+ <li>Ruby: <%== RUBY_VERSION %></li>
174
+ <li>Rack: <%== Rack::RELEASE %></li>
175
+ <li>Rails: <%== Rails.version %></li>
176
+ <li>Pagy: <%== Pagy::VERSION %></li>
177
+ </ul>
178
+
179
+ <h4>Collection</h4>
180
+ <div class="collection">
181
+ <% @comments.each do |comment| %>
182
+ <p style="margin: 0;"><%= comment.body %></p>
183
+ <% end %>
184
+ </div>
185
+ <hr>
186
+
187
+ <h4>pagy_nav</h4>
188
+ <%== pagy_nav(@pagy) %>
189
+
190
+ <h4>pagy_nav_js</h4>
191
+ <%== pagy_nav_js(@pagy) %>
192
+
193
+ <h4>pagy_combo_nav_js</h4>
194
+ <%== pagy_combo_nav_js(@pagy) %>
195
+
196
+ <h4>pagy_items_selector_js</h4>
197
+ <%== pagy_items_selector_js(@pagy) %>
198
+
199
+ <h4>pagy_info</h4>
200
+ <%== pagy_info(@pagy) %>
201
+ </div>
202
+
203
+ </body>
204
+ </html>
205
+ ERB