kaminari-core 1.2.2 → 1.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/views/kaminari/_first_page.html.erb +2 -1
  3. data/app/views/kaminari/_first_page.html.haml +2 -1
  4. data/app/views/kaminari/_first_page.html.slim +2 -1
  5. data/app/views/kaminari/_last_page.html.erb +2 -1
  6. data/app/views/kaminari/_last_page.html.haml +2 -1
  7. data/app/views/kaminari/_last_page.html.slim +2 -1
  8. data/app/views/kaminari/_next_page.html.erb +2 -1
  9. data/app/views/kaminari/_next_page.html.haml +2 -1
  10. data/app/views/kaminari/_next_page.html.slim +2 -1
  11. data/app/views/kaminari/_page.html.erb +2 -1
  12. data/app/views/kaminari/_page.html.haml +2 -1
  13. data/app/views/kaminari/_page.html.slim +2 -1
  14. data/app/views/kaminari/_paginator.html.erb +1 -0
  15. data/app/views/kaminari/_paginator.html.haml +5 -3
  16. data/app/views/kaminari/_paginator.html.slim +5 -3
  17. data/app/views/kaminari/_prev_page.html.erb +2 -1
  18. data/app/views/kaminari/_prev_page.html.haml +2 -1
  19. data/app/views/kaminari/_prev_page.html.slim +2 -1
  20. data/config/locales/kaminari.yml +1 -1
  21. data/kaminari-core.gemspec +7 -0
  22. data/lib/generators/kaminari/views_generator.rb +38 -18
  23. data/lib/kaminari/core/version.rb +1 -1
  24. data/lib/kaminari/core.rb +4 -0
  25. data/lib/kaminari/engine.rb +3 -0
  26. data/lib/kaminari/helpers/helper_methods.rb +21 -6
  27. data/lib/kaminari/helpers/paginator.rb +27 -17
  28. data/lib/kaminari/helpers/tags.rb +103 -34
  29. data/lib/kaminari/models/array_extension.rb +18 -2
  30. data/lib/kaminari/models/configuration_methods.rb +1 -1
  31. data/lib/kaminari/models/page_scope_methods.rb +28 -15
  32. metadata +94 -89
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f97cdb29c6cc0f87f4a3b2439bc98d4015894053aece52f9685f9053d828eee2
4
- data.tar.gz: fda4562a4e0fe69e90af6276b78575dc6dbbe6f42f98ffecd70bd54ddf7cf5cc
3
+ metadata.gz: d08a6963a92273028b03d21b148a1a7d4fb8f7033b315e1af492b54eaf9ba790
4
+ data.tar.gz: 6aa9625e5db4476c1e76deaa7e548e9821dc19411ff09c753cbb9a16c146e81e
5
5
  SHA512:
6
- metadata.gz: 0dbaec420bee38126a89931872d0d4dcc37772a7bb22d0c97844399b95c55cc4677a2634d1b908b1c4c5c60a0319ab5b88d8b7bb4f01658db3ecc52400eb9c94
7
- data.tar.gz: a5294c22cd10b649243d4ebd4ac85481e1ae16b956d2777121926026eb21f2c3ec6c07a799ca02271f0348a76f9cc4fcf409ce0cdbe69672289fdca1e745e800
6
+ metadata.gz: 497e6516b7f39d799c9c69a772c3985d1da0f4714e42f1d011686b273d178c534513b074de56d5c888e98ec4f70ca78718c211b918a2d584b5b0ef040b8f697d
7
+ data.tar.gz: 32cce623d1212f46a77c41974ef225c93b152fcb7ed41de7f03e21c825c8b42b2e75ec1777afd0e0719ea9aa27c77238195a1ce2b16f8ee433fcc04b0cbc212c
@@ -5,7 +5,8 @@
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote
8
+ data: data-* attributes
8
9
  -%>
9
10
  <span class="first">
10
- <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote %>
11
+ <%= link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote, data: data %>
11
12
  </span>
@@ -5,5 +5,6 @@
5
5
  -# total_pages: total number of pages
6
6
  -# per_page: number of items to fetch per page
7
7
  -# remote: data-remote
8
+ -# data: data-* attributes
8
9
  %span.first
9
- = link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote
10
+ = link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote, data: data
@@ -5,6 +5,7 @@
5
5
  total_pages : total number of pages
6
6
  per_page : number of items to fetch per page
7
7
  remote : data-remote
8
+ data : data-* attributes
8
9
  span.first
9
- == link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote
10
+ == link_to_unless current_page.first?, t('views.pagination.first').html_safe, url, remote: remote, data: data
10
11
  '
@@ -5,7 +5,8 @@
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote
8
+ data: data-* attributes
8
9
  -%>
9
10
  <span class="last">
10
- <%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote %>
11
+ <%= link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote, data: data %>
11
12
  </span>
@@ -5,5 +5,6 @@
5
5
  -# total_pages: total number of pages
6
6
  -# per_page: number of items to fetch per page
7
7
  -# remote: data-remote
8
+ -# data: data-* attributes
8
9
  %span.last
9
- = link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote
10
+ = link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote, data: data
@@ -5,6 +5,7 @@
5
5
  total_pages : total number of pages
6
6
  per_page : number of items to fetch per page
7
7
  remote : data-remote
8
+ data : data-* attributes
8
9
  span.last
9
- == link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote
10
+ == link_to_unless current_page.last?, t('views.pagination.last').html_safe, url, remote: remote, data: data
10
11
  '
@@ -5,7 +5,8 @@
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote
8
+ data: data-* attributes
8
9
  -%>
9
10
  <span class="next">
10
- <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote %>
11
+ <%= link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote, data: data %>
11
12
  </span>
@@ -5,5 +5,6 @@
5
5
  -# total_pages: total number of pages
6
6
  -# per_page: number of items to fetch per page
7
7
  -# remote: data-remote
8
+ -# data: data-* attributes
8
9
  %span.next
9
- = link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote
10
+ = link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote, data: data
@@ -5,6 +5,7 @@
5
5
  total_pages : total number of pages
6
6
  per_page : number of items to fetch per page
7
7
  remote : data-remote
8
+ data : data-* attributes
8
9
  span.next
9
- == link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote
10
+ == link_to_unless current_page.last?, t('views.pagination.next').html_safe, url, rel: 'next', remote: remote, data: data
10
11
  '
@@ -6,7 +6,8 @@
6
6
  total_pages: total number of pages
7
7
  per_page: number of items to fetch per page
8
8
  remote: data-remote
9
+ data: data-* attributes
9
10
  -%>
10
11
  <span class="page<%= ' current' if page.current? %>">
11
- <%= link_to_unless page.current?, page, url, {remote: remote, rel: page.rel} %>
12
+ <%= link_to_unless page.current?, page, url, {remote: remote, data: data, rel: page.rel} %>
12
13
  </span>
@@ -6,5 +6,6 @@
6
6
  -# total_pages: total number of pages
7
7
  -# per_page: number of items to fetch per page
8
8
  -# remote: data-remote
9
+ -# data: data-* attributes
9
10
  %span{class: "page#{' current' if page.current?}"}
10
- = link_to_unless page.current?, page, url, {remote: remote, rel: page.rel}
11
+ = link_to_unless page.current?, page, url, {remote: remote, data: data, rel: page.rel}
@@ -6,6 +6,7 @@
6
6
  total_pages : total number of pages
7
7
  per_page : number of items to fetch per page
8
8
  remote : data-remote
9
+ data : data-* attributes
9
10
  span class="page#{' current' if page.current?}"
10
- == link_to_unless page.current?, page, url, {remote: remote, rel: page.rel}
11
+ == link_to_unless page.current?, page, url, {remote: remote, data: data, rel: page.rel}
11
12
  '
@@ -4,6 +4,7 @@
4
4
  total_pages: total number of pages
5
5
  per_page: number of items to fetch per page
6
6
  remote: data-remote
7
+ data: data-* attributes
7
8
  paginator: the paginator that renders the pagination tags inside
8
9
  -%>
9
10
  <%= paginator.render do -%>
@@ -4,9 +4,10 @@
4
4
  -# total_pages: total number of pages
5
5
  -# per_page: number of items to fetch per page
6
6
  -# remote: data-remote
7
+ -# data: data-* attributes
7
8
  -# paginator: the paginator that renders the pagination tags inside
8
9
  = paginator.render do
9
- %nav.pagination
10
+ %nav.pagination{role: "navigation", "aria-label" => "pager"}
10
11
  = first_page_tag unless current_page.first?
11
12
  = prev_page_tag unless current_page.first?
12
13
  - each_page do |page|
@@ -14,5 +15,6 @@
14
15
  = page_tag page
15
16
  - elsif !page.was_truncated?
16
17
  = gap_tag
17
- = next_page_tag unless current_page.last?
18
- = last_page_tag unless current_page.last?
18
+ - unless current_page.out_of_range?
19
+ = next_page_tag unless current_page.last?
20
+ = last_page_tag unless current_page.last?
@@ -4,10 +4,11 @@
4
4
  total_pages : total number of pages
5
5
  per_page : number of items to fetch per page
6
6
  remote : data-remote
7
+ data : data-* attributes
7
8
  paginator : the paginator that renders the pagination tags inside
8
9
 
9
10
  == paginator.render do
10
- nav.pagination
11
+ nav.pagination role="navigation" aria-label="pager"
11
12
  == first_page_tag unless current_page.first?
12
13
  == prev_page_tag unless current_page.first?
13
14
  - each_page do |page|
@@ -15,5 +16,6 @@
15
16
  == page_tag page
16
17
  - elsif !page.was_truncated?
17
18
  == gap_tag
18
- == next_page_tag unless current_page.last?
19
- == last_page_tag unless current_page.last?
19
+ - unless current_page.out_of_range?
20
+ == next_page_tag unless current_page.last?
21
+ == last_page_tag unless current_page.last?
@@ -5,7 +5,8 @@
5
5
  total_pages: total number of pages
6
6
  per_page: number of items to fetch per page
7
7
  remote: data-remote
8
+ data: data-* attributes
8
9
  -%>
9
10
  <span class="prev">
10
- <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote %>
11
+ <%= link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote, data: data %>
11
12
  </span>
@@ -5,5 +5,6 @@
5
5
  -# total_pages: total number of pages
6
6
  -# per_page: number of items to fetch per page
7
7
  -# remote: data-remote
8
+ -# data: data-* attributes
8
9
  %span.prev
9
- = link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote
10
+ = link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote, data: data
@@ -5,6 +5,7 @@
5
5
  total_pages : total number of pages
6
6
  per_page : number of items to fetch per page
7
7
  remote : data-remote
8
+ data : data-* attributes
8
9
  span.prev
9
- == link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote
10
+ == link_to_unless current_page.first?, t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote, data: data
10
11
  '
@@ -20,4 +20,4 @@ en:
20
20
  one: "Displaying <b>1</b> %{entry_name}"
21
21
  other: "Displaying <b>all %{count}</b> %{entry_name}"
22
22
  more_pages:
23
- display_entries: "Displaying %{entry_name} <b>%{first}&nbsp;-&nbsp;%{last}</b> of <b>%{total}</b> in total"
23
+ display_entries: "Displaying %{entry_name} <b>%{first}–%{last}</b> of <b>%{total}</b> in total"
@@ -14,6 +14,13 @@ Gem::Specification.new do |spec|
14
14
  spec.description = 'kaminari-core includes pagination logic independent from ORMs and view libraries'
15
15
  spec.homepage = 'https://github.com/kaminari/kaminari'
16
16
  spec.license = "MIT"
17
+
18
+ spec.metadata = {
19
+ 'changelog_uri' => 'https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md',
20
+ 'source_code_uri' => 'https://github.com/kaminari/kaminari/tree/master/kaminari-core',
21
+ 'rubygems_mfa_required' => 'true'
22
+ }
23
+
17
24
  spec.required_ruby_version = '>= 2.0.0'
18
25
 
19
26
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -9,8 +9,9 @@ module Kaminari
9
9
  class_option :template_engine, type: :string, aliases: '-e', desc: 'Template engine for the views. Available options are "erb", "haml", and "slim".'
10
10
  class_option :views_prefix, type: :string, desc: 'Prefix for path to put views in.'
11
11
 
12
- def self.banner #:nodoc:
13
- <<-BANNER.chomp
12
+ class << self
13
+ def banner #:nodoc:
14
+ <<-BANNER.chomp
14
15
  rails g kaminari:views THEME [options]
15
16
 
16
17
  Copies all paginator partial templates to your application.
@@ -21,29 +22,35 @@ rails g kaminari:views THEME [options]
21
22
  This one is used internally while you don't override the partials.
22
23
  #{themes.map {|t| " - #{t.name}\n#{t.description}"}.join("\n")}
23
24
  BANNER
25
+ end
26
+
27
+ def themes
28
+ @themes ||= GitHubApiHelper.get_files_in_master.group_by {|fn, _| fn[0...(fn.index('/') || 0)]}.delete_if {|fn, _| fn.blank?}.map do |name, files|
29
+ Theme.new name, files
30
+ end
31
+ rescue *GitHubApiHelper::NETWORK_ERRORS
32
+ []
33
+ end
24
34
  end
25
35
 
26
36
  desc ''
27
37
  def copy_or_fetch #:nodoc:
28
38
  return copy_default_views if file_name == 'default'
29
39
 
30
- if (theme = self.class.themes.detect {|t| t.name == file_name})
40
+ if self.class.themes.empty?
41
+ say "could not fetch the themes from GitHub. Please try again later."
42
+ elsif (theme = self.class.themes.detect {|t| t.name == file_name})
31
43
  if download_templates(theme).empty?
32
44
  say "template_engine: #{template_engine} is not available for theme: #{file_name}"
33
45
  end
34
46
  else
35
47
  say "no such theme: #{file_name}\n available themes: #{self.class.themes.map(&:name).join ', '}"
36
48
  end
49
+ rescue *GitHubApiHelper::NETWORK_ERRORS => e
50
+ say "could not download the templates from GitHub (#{e.message}). Please try again later."
37
51
  end
38
52
 
39
53
  private
40
- def self.themes
41
- @themes ||= GitHubApiHelper.get_files_in_master.group_by {|fn, _| fn[0...(fn.index('/') || 0)]}.delete_if {|fn, _| fn.blank?}.map do |name, files|
42
- Theme.new name, files
43
- end
44
- rescue SocketError
45
- []
46
- end
47
54
 
48
55
  def download_templates(theme)
49
56
  theme.templates_for(template_engine).each do |template|
@@ -68,14 +75,21 @@ BANNER
68
75
  end
69
76
 
70
77
  def template_engine
71
- engine = options[:template_engine].try(:to_s).try(:downcase)
78
+ @template_engine ||= begin
79
+ engine = options[:template_engine].try(:to_s).try(:downcase).presence || 'erb'
72
80
 
73
- if engine == 'haml' || engine == 'slim'
74
- ActiveSupport::Deprecation.warn 'The -e option is deprecated and will be removed in the near future. Please use the html2slim gem or the html2haml gem ' \
75
- 'to convert erb templates manually.'
76
- end
81
+ if engine == 'haml' || engine == 'slim'
82
+ Kaminari.deprecator.warn 'The -e option is deprecated and will be removed in the near future. Please use the html2slim gem or the html2haml gem ' \
83
+ 'to convert erb templates manually.'
84
+ end
77
85
 
78
- engine || 'erb'
86
+ if %w[erb haml slim].include?(engine)
87
+ engine
88
+ else
89
+ say "template_engine: #{engine} is not supported. Falling back to erb."
90
+ 'erb'
91
+ end
92
+ end
79
93
  end
80
94
  end
81
95
 
@@ -103,6 +117,8 @@ BANNER
103
117
  file = @templates.detect(&:description?)
104
118
  return "#{' ' * 12}#{name}" unless file
105
119
  GitHubApiHelper.get_content_for("#{@name}/#{file.name}").chomp.gsub(/^/, ' ' * 12)
120
+ rescue *GitHubApiHelper::NETWORK_ERRORS
121
+ "#{' ' * 12}#{name}"
106
122
  end
107
123
 
108
124
  def templates_for(template_engine) #:nodoc:
@@ -112,12 +128,16 @@ BANNER
112
128
 
113
129
  module GitHubApiHelper
114
130
  require 'open-uri'
131
+ require 'net/http'
132
+
133
+ # e.g. offline, timed out, or exceeded the API rate limit
134
+ NETWORK_ERRORS = [SocketError, SystemCallError, Timeout::Error, OpenSSL::SSL::SSLError, OpenURI::HTTPError].freeze
115
135
 
116
136
  def get_files_in_master
117
137
  master_tree_sha = URI.open('https://api.github.com/repos/amatsuda/kaminari_themes/git/refs/heads/master') do |json|
118
138
  ActiveSupport::JSON.decode(json.read)['object']['sha']
119
139
  end
120
- URI.open('https://api.github.com/repos/amatsuda/kaminari_themes/git/trees/' + master_tree_sha + '?recursive=1') do |json|
140
+ URI.parse("https://api.github.com/repos/amatsuda/kaminari_themes/git/trees/#{master_tree_sha}?recursive=1").open do |json|
121
141
  blobs = ActiveSupport::JSON.decode(json.read)['tree'].find_all {|i| i['type'] == 'blob' }
122
142
  blobs.map do |blob|
123
143
  [blob['path'], blob['sha']]
@@ -127,7 +147,7 @@ BANNER
127
147
  module_function :get_files_in_master
128
148
 
129
149
  def get_content_for(path)
130
- URI.open('https://api.github.com/repos/amatsuda/kaminari_themes/contents/' + path) do |json|
150
+ URI.parse("https://api.github.com/repos/amatsuda/kaminari_themes/contents/#{path}").open do |json|
131
151
  Base64.decode64(ActiveSupport::JSON.decode(json.read)['content'])
132
152
  end
133
153
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kaminari
4
4
  module Core
5
- VERSION = '1.2.2'
5
+ VERSION = '1.3.0'
6
6
  end
7
7
  end
data/lib/kaminari/core.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kaminari
4
+ def self.deprecator
5
+ @deprecator ||= ActiveSupport::Deprecation.new("2.0", "kaminari-core")
6
+ end
4
7
  end
5
8
 
6
9
  # load Rails/Railtie
@@ -14,6 +17,7 @@ end
14
17
  require 'kaminari/config'
15
18
  require 'kaminari/exceptions'
16
19
  require 'kaminari/helpers/paginator'
20
+ require 'kaminari/helpers/helper_methods'
17
21
  require 'kaminari/models/page_scope_methods'
18
22
  require 'kaminari/models/configuration_methods'
19
23
  require 'kaminari/models/array_extension'
@@ -2,5 +2,8 @@
2
2
 
3
3
  module Kaminari #:nodoc:
4
4
  class Engine < ::Rails::Engine #:nodoc:
5
+ initializer :deprecator do |app|
6
+ app.deprecators[:kaminari] = Kaminari.deprecator if app.respond_to?(:deprecators)
7
+ end
5
8
  end
6
9
  end
@@ -44,7 +44,7 @@ module Kaminari
44
44
  alias url_to_next_page next_page_url
45
45
 
46
46
  def path_to_next_url(scope, options = {})
47
- ActiveSupport::Deprecation.warn 'path_to_next_url is deprecated. Use next_page_url or url_to_next_page instead.'
47
+ Kaminari.deprecator.warn 'path_to_next_url is deprecated. Use next_page_url or url_to_next_page instead.'
48
48
  next_page_url(scope, options)
49
49
  end
50
50
 
@@ -110,10 +110,12 @@ module Kaminari
110
110
  # * <tt>:params</tt> - url_for parameters for the links (:controller, :action, etc.)
111
111
  # * <tt>:param_name</tt> - parameter name for page number in the links (:page by default)
112
112
  # * <tt>:remote</tt> - Ajax? (false by default)
113
+ # * <tt>:data</tt> - data-* attributes for the links (e.g. <tt>{turbo_frame: 'users'}</tt>)
113
114
  # * <tt>:paginator_class</tt> - Specify a custom Paginator (Kaminari::Helpers::Paginator by default)
114
115
  # * <tt>:template</tt> - Specify a custom template renderer for rendering the Paginator (receiver by default)
115
116
  # * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
116
117
  def paginate(scope, paginator_class: Kaminari::Helpers::Paginator, template: nil, **options)
118
+ options[:data] ||= {}
117
119
  options[:total_pages] ||= scope.total_pages
118
120
  options.reverse_merge! current_page: scope.current_page, per_page: scope.limit_value, remote: false
119
121
 
@@ -193,23 +195,36 @@ module Kaminari
193
195
  #
194
196
  # By default, the message will use the humanized class name of objects
195
197
  # in collection: for instance, "project types" for ProjectType models.
196
- # The namespace will be cutted out and only the last name will be used.
198
+ # The namespace will be cut out and only the last name will be used.
197
199
  # Override this with the <tt>:entry_name</tt> parameter:
198
200
  #
199
201
  # <%= page_entries_info @posts, entry_name: 'item' %>
200
202
  # #-> Displaying items 6 - 10 of 26 in total
201
203
  def page_entries_info(collection, entry_name: nil)
204
+ records = collection.respond_to?(:records) ? collection.records : collection.to_a
205
+ page_size = records.size
202
206
  entry_name = if entry_name
203
- entry_name.pluralize(collection.size, I18n.locale)
207
+ pluralized = entry_name.pluralize(page_size, I18n.locale)
208
+ entry_name.html_safe? ? pluralized.html_safe : pluralized
204
209
  else
205
- collection.entry_name(count: collection.size).downcase
210
+ collection.entry_name(count: page_size).downcase
206
211
  end
212
+ # the translated message is marked as html_safe, so the interpolated entry_name has to be escaped here
213
+ entry_name = ERB::Util.html_escape entry_name
207
214
 
208
- if collection.total_pages < 2
215
+ if collection.out_of_range?
216
+ # an out of range page displays no entries
217
+ t('helpers.page_entries_info.one_page.display_entries', entry_name: entry_name, count: 0)
218
+ elsif collection.total_pages < 2
209
219
  t('helpers.page_entries_info.one_page.display_entries', entry_name: entry_name, count: collection.total_count)
210
220
  else
211
221
  from = collection.offset_value + 1
212
- to = collection.offset_value + (collection.respond_to?(:records) ? collection.records : collection.to_a).size
222
+ to =
223
+ if collection.is_a? ::Kaminari::PaginatableArray
224
+ [collection.offset_value + collection.limit_value, collection.total_count].min
225
+ else
226
+ collection.offset_value + page_size
227
+ end
213
228
 
214
229
  t('helpers.page_entries_info.more_pages.display_entries', entry_name: entry_name, first: from, last: to, total: collection.total_count)
215
230
  end.html_safe
@@ -8,9 +8,13 @@ module Kaminari
8
8
  # The main container tag
9
9
  class Paginator < Tag
10
10
  def initialize(template, window: nil, outer_window: Kaminari.config.outer_window, left: Kaminari.config.left, right: Kaminari.config.right, inner_window: Kaminari.config.window, **options) #:nodoc:
11
+ super template, **options
12
+
11
13
  @window_options = {window: window || inner_window, left: left.zero? ? outer_window : left, right: right.zero? ? outer_window : right}
12
14
 
13
- @template, @options, @theme, @views_prefix, @last = template, options, options[:theme], options[:views_prefix], nil
15
+ @last = nil
16
+ # shared by all the tags in this paginator
17
+ @url_cache, @partial_cache = {}, {}
14
18
  @window_options.merge! @options
15
19
  @window_options[:current_page] = @options[:current_page] = PageProxy.new(@window_options, @options[:current_page], nil)
16
20
 
@@ -59,13 +63,13 @@ module Kaminari
59
63
  private :relevant_pages
60
64
 
61
65
  def page_tag(page)
62
- @last = Page.new @template, **@options.merge(page: page)
66
+ @last = Page.new @template, param_name: @param_name, theme: @theme, views_prefix: @views_prefix, internal_params: @params, internal_url_cache: @url_cache, internal_partial_cache: @partial_cache, **@options.merge(page: page)
63
67
  end
64
68
 
65
69
  %w[first_page prev_page next_page last_page gap].each do |tag|
66
70
  eval <<-DEF, nil, __FILE__, __LINE__ + 1
67
71
  def #{tag}_tag
68
- @last = #{tag.classify}.new @template, **@options
72
+ @last = #{tag.classify}.new @template, param_name: @param_name, theme: @theme, views_prefix: @views_prefix, internal_params: @params, internal_url_cache: @url_cache, internal_partial_cache: @partial_cache, **@options
69
73
  end
70
74
  DEF
71
75
  end
@@ -78,8 +82,8 @@ module Kaminari
78
82
  end
79
83
 
80
84
  # delegates view helper methods to @template
81
- def method_missing(name, *args, &block)
82
- @template.respond_to?(name) ? @template.send(name, *args, &block) : super
85
+ def method_missing(name, *args, **kwargs, &block)
86
+ @template.respond_to?(name) ? @template.send(name, *args, **kwargs, &block) : super
83
87
  end
84
88
  private :method_missing
85
89
 
@@ -88,7 +92,13 @@ module Kaminari
88
92
  include Comparable
89
93
 
90
94
  def initialize(options, page, last) #:nodoc:
91
- @options, @page, @last = options, page, last
95
+ @page = page
96
+ @current_page = options[:current_page]
97
+ @total_pages = options[:total_pages]
98
+ @left = options[:left]
99
+ @right = options[:right]
100
+ @window = options[:window]
101
+ @was_truncated = last.is_a? Gap
92
102
  end
93
103
 
94
104
  # the page number
@@ -98,7 +108,7 @@ module Kaminari
98
108
 
99
109
  # current page or not
100
110
  def current?
101
- @page == @options[:current_page]
111
+ @page == @current_page
102
112
  end
103
113
 
104
114
  # the first page or not
@@ -108,17 +118,17 @@ module Kaminari
108
118
 
109
119
  # the last page or not
110
120
  def last?
111
- @page == @options[:total_pages]
121
+ @page == @total_pages
112
122
  end
113
123
 
114
124
  # the previous page or not
115
125
  def prev?
116
- @page == @options[:current_page] - 1
126
+ @page == @current_page - 1
117
127
  end
118
128
 
119
129
  # the next page or not
120
130
  def next?
121
- @page == @options[:current_page] + 1
131
+ @page == @current_page + 1
122
132
  end
123
133
 
124
134
  # relationship with the current page
@@ -132,33 +142,33 @@ module Kaminari
132
142
 
133
143
  # within the left outer window or not
134
144
  def left_outer?
135
- @page <= @options[:left]
145
+ @page <= @left
136
146
  end
137
147
 
138
148
  # within the right outer window or not
139
149
  def right_outer?
140
- @options[:total_pages] - @page < @options[:right]
150
+ @total_pages - @page < @right
141
151
  end
142
152
 
143
153
  # inside the inner window or not
144
154
  def inside_window?
145
- (@options[:current_page] - @page).abs <= @options[:window]
155
+ (@current_page - @page).abs <= @window
146
156
  end
147
157
 
148
158
  # Current page is an isolated gap or not
149
159
  def single_gap?
150
- ((@page == @options[:current_page] - @options[:window] - 1) && (@page == @options[:left] + 1)) ||
151
- ((@page == @options[:current_page] + @options[:window] + 1) && (@page == @options[:total_pages] - @options[:right]))
160
+ ((@page == @current_page - @window - 1) && (@page == @left + 1)) ||
161
+ ((@page == @current_page + @window + 1) && (@page == @total_pages - @right))
152
162
  end
153
163
 
154
164
  # The page number exceeds the range of pages or not
155
165
  def out_of_range?
156
- @page > @options[:total_pages]
166
+ @page > @total_pages
157
167
  end
158
168
 
159
169
  # The last rendered tag was "truncated" or not
160
170
  def was_truncated?
161
- @last.is_a? Gap
171
+ @was_truncated
162
172
  end
163
173
 
164
174
  #Should we display the link tag?
@@ -2,7 +2,8 @@
2
2
 
3
3
  module Kaminari
4
4
  module Helpers
5
- PARAM_KEY_EXCEPT_LIST = [:authenticity_token, :commit, :utf8, :_method, :script_name, :original_script_name].freeze
5
+ PARAM_KEY_EXCEPT_LIST = [:authenticity_token, :commit, :utf8, :_method, :script_name, :original_script_name,
6
+ :subdomain, :domain, :tld_length, :host, :port, :protocol, :anchor, :trailing_slash, :params, :path_params].freeze
6
7
 
7
8
  # A tag stands for an HTML tag inside the paginator.
8
9
  # Basically, a tag has its own partial template file, so every tag can be
@@ -17,56 +18,124 @@ module Kaminari
17
18
  # installed template will be used.
18
19
  # e.g.) Paginator -> $GEM_HOME/kaminari-x.x.x/app/views/kaminari/_paginator.html.erb
19
20
  class Tag
20
- def initialize(template, params: {}, param_name: nil, theme: nil, views_prefix: nil, **options) #:nodoc:
21
+ # A page number that is unlikely to appear in any URL, which stands in for the actual page number in the cached URL
22
+ PAGE_PLACEHOLDER = rand(10**17...10**18)
23
+
24
+ def initialize(template, params: nil, param_name: nil, theme: nil, views_prefix: nil, internal_params: nil, internal_url_cache: nil, internal_partial_cache: nil, **options) #:nodoc:
21
25
  @template, @theme, @views_prefix, @options = template, theme, views_prefix, options
22
26
  @param_name = param_name || Kaminari.config.param_name
23
- @params = template.params
24
- # @params in Rails 5 no longer inherits from Hash
25
- @params = @params.to_unsafe_h if @params.respond_to?(:to_unsafe_h)
26
- @params = @params.with_indifferent_access
27
- @params.except!(*PARAM_KEY_EXCEPT_LIST)
28
- @params.merge! params
27
+ @url_cache, @partial_cache = internal_url_cache, internal_partial_cache
28
+
29
+ if internal_params
30
+ @params = internal_params
31
+ else
32
+ @params = template.params
33
+ # @params in Rails 5 no longer inherits from Hash
34
+ @params = if @params.respond_to?(:to_unsafe_h)
35
+ @params.to_unsafe_h
36
+ else
37
+ @params.with_indifferent_access
38
+ end
39
+ @params.except!(*PARAM_KEY_EXCEPT_LIST)
40
+ @params.merge! params if params
41
+ end
29
42
  end
30
43
 
31
44
  def to_s(locals = {}) #:nodoc:
32
- formats = (@template.respond_to?(:formats) ? @template.formats : Array(@template.params[:format])) + [:html]
33
- @template.render partial: partial_path, locals: @options.merge(locals), formats: formats
45
+ formats = @template.respond_to?(:formats) ? @template.formats : Array(@template.params[:format])
46
+ if @partial_cache && formats.include?(:html) && @template.respond_to?(:lookup_context)
47
+ render_cached_partial @options.merge(locals)
48
+ else
49
+ formats += [:html] unless formats.include? :html
50
+ @template.render partial: partial_path, locals: @options.merge(locals), formats: formats
51
+ end
34
52
  end
35
53
 
36
54
  def page_url_for(page)
55
+ @url_cache ? cached_page_url_for(page.to_i) : generate_page_url(page)
56
+ end
57
+
58
+ private
59
+
60
+ # Looking up a partial template is costly, so the paginator looks up each partial only once, and then renders the
61
+ # template directly in the same way as `render partial:` does.
62
+ # This is done only when the formats already include :html, which means the formats that `to_s` would pass to
63
+ # `render` are the same as the current ones, and so finding and rendering the template doesn't depend on the formats.
64
+ def render_cached_partial(locals)
65
+ path, keys = partial_path, locals.keys
66
+ cached_keys, template = @partial_cache[path]
67
+ unless template && (cached_keys == keys)
68
+ template = @template.lookup_context.find_template(path, [], true, keys)
69
+ @partial_cache[path] = [keys, template]
70
+ end
71
+ # `render partial:` in Action View 4 also puts the partial name into local_assigns (e.g. {gap: nil, ...})
72
+ if ActionView::VERSION::MAJOR < 5
73
+ name = File.basename(path).to_sym
74
+ locals[name] = nil unless locals.key? name
75
+ end
76
+
77
+ ActiveSupport::Notifications.instrument('render_partial.action_view', identifier: template.identifier, layout: nil, locals: locals) do
78
+ template.render(@template, locals) {|*name| @template._layout_for(*name) }
79
+ end
80
+ end
81
+
82
+ def generate_page_url(page)
37
83
  params = params_for(page)
38
84
  params[:only_path] = true
39
85
  @template.url_for params
40
86
  end
41
87
 
42
- private
88
+ # Generating URLs is costly, so the paginator generates the URL only once with a placeholder page number,
89
+ # and then builds the URL for each page by replacing the placeholder
90
+ def cached_page_url_for(page)
91
+ @url_cache.fetch(page) do
92
+ url_template = @url_cache[:url_template]
93
+ @url_cache[page] = if url_template && (page > 1)
94
+ url_template.sub(PAGE_PLACEHOLDER.to_s, page.to_s)
95
+ else
96
+ generate_page_url(page).tap {|url| build_url_template(page, url) if url_template.nil? && (page > 1) }
97
+ end
98
+ end
99
+ end
43
100
 
44
- def params_for(page)
45
- page_params = Rack::Utils.parse_nested_query("#{@param_name}=#{page}")
46
- page_params = @params.deep_merge(page_params)
47
-
48
- if !Kaminari.config.params_on_first_page && (page <= 1)
49
- # This converts a hash:
50
- # from: {other: "params", page: 1}
51
- # to: {other: "params", page: nil}
52
- # (when @param_name == "page")
53
- #
54
- # from: {other: "params", user: {name: "yuki", page: 1}}
55
- # to: {other: "params", user: {name: "yuki", page: nil}}
56
- # (when @param_name == "user[page]")
57
- @param_name.to_s.scan(/[\w\.]+/)[0..-2].inject(page_params){|h, k| h[k] }[$&] = nil
101
+ # Use the URL with the placeholder only when it builds exactly the same URL as url_for does.
102
+ # Otherwise (e.g. when the routes constrain the page number), fall back to calling url_for for each page.
103
+ def build_url_template(page, url)
104
+ url_template = begin
105
+ generate_page_url PAGE_PLACEHOLDER
106
+ rescue StandardError
107
+ nil
58
108
  end
109
+ @url_cache[:url_template] = url_template && (url_template.scan(PAGE_PLACEHOLDER.to_s).size == 1) && (url_template.sub(PAGE_PLACEHOLDER.to_s, page.to_s) == url) ? url_template : false
110
+ end
59
111
 
60
- page_params
112
+ def params_for(page)
113
+ if (@param_name == :page) || !@param_name.to_s.include?('[')
114
+ page_val = !Kaminari.config.params_on_first_page && (page <= 1) ? nil : page
115
+ @params[@param_name] = page_val
116
+ @params
117
+ else
118
+ page_params = Rack::Utils.parse_nested_query("#{@param_name}=#{page}")
119
+ page_params = @params.deep_merge(page_params)
120
+
121
+ if !Kaminari.config.params_on_first_page && (page <= 1)
122
+ # This converts a hash:
123
+ # from: {other: "params", page: 1}
124
+ # to: {other: "params", page: nil}
125
+ # (when @param_name == "page")
126
+ #
127
+ # from: {other: "params", user: {name: "yuki", page: 1}}
128
+ # to: {other: "params", user: {name: "yuki", page: nil}}
129
+ # (when @param_name == "user[page]")
130
+ @param_name.to_s.scan(/[\w.]+/)[0..-2].inject(page_params){|h, k| h[k] }[$&] = nil
131
+ end
132
+
133
+ page_params
134
+ end
61
135
  end
62
136
 
63
137
  def partial_path
64
- [
65
- @views_prefix,
66
- "kaminari",
67
- @theme,
68
- self.class.name.demodulize.underscore
69
- ].compact.join("/").gsub('//', '/')
138
+ "#{@views_prefix}/kaminari/#{@theme}/#{self.class.name.demodulize.underscore}".gsub('//', '/')
70
139
  end
71
140
  end
72
141
 
@@ -124,7 +193,7 @@ module Kaminari
124
193
  # params in Rails 5 may not be a Hash either,
125
194
  # so it must be converted to a Hash to be merged into @params
126
195
  if params && params.respond_to?(:to_unsafe_h)
127
- ActiveSupport::Deprecation.warn 'Explicitly passing params to helpers could be omitted.'
196
+ Kaminari.deprecator.warn 'Explicitly passing params to helpers could be omitted.'
128
197
  params = params.to_unsafe_h
129
198
  end
130
199
 
@@ -145,7 +214,7 @@ module Kaminari
145
214
  # params in Rails 5 may not be a Hash either,
146
215
  # so it must be converted to a Hash to be merged into @params
147
216
  if params && params.respond_to?(:to_unsafe_h)
148
- ActiveSupport::Deprecation.warn 'Explicitly passing params to helpers could be omitted.'
217
+ Kaminari.deprecator.warn 'Explicitly passing params to helpers could be omitted.'
149
218
  params = params.to_unsafe_h
150
219
  end
151
220
 
@@ -41,13 +41,19 @@ module Kaminari
41
41
  # items at the specified "page"
42
42
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
43
43
  def #{Kaminari.config.page_method_name}(num = 1)
44
+ num = num.respond_to?(:to_i) ? num.to_i : 1
44
45
  offset(limit_value * ((num = num.to_i - 1) < 0 ? 0 : num))
45
46
  end
46
47
  RUBY
47
48
 
48
49
  # returns another chunk of the original array
49
50
  def limit(num)
50
- self.class.new @_original_array, limit: num, offset: @_offset_value, total_count: @_total_count, padding: @_padding
51
+ spawn limit: num, offset: @_offset_value
52
+ end
53
+
54
+ # overridden by Kaminari::PageScopeMethods once paginated
55
+ def paginated?
56
+ false
51
57
  end
52
58
 
53
59
  # total item numbers of the original array
@@ -57,7 +63,17 @@ module Kaminari
57
63
 
58
64
  # returns another chunk of the original array
59
65
  def offset(num)
60
- self.class.new @_original_array, limit: @_limit_value, offset: num, total_count: @_total_count, padding: @_padding
66
+ spawn limit: @_limit_value, offset: num
67
+ end
68
+
69
+ private
70
+
71
+ # Builds another chunk of the original array, carrying over the per page settings given to this one
72
+ def spawn(limit:, offset:)
73
+ self.class.new(@_original_array, limit: limit, offset: offset, total_count: @_total_count, padding: @_padding).tap do |array|
74
+ array.instance_variable_set :@_per, @_per if defined?(@_per)
75
+ array.instance_variable_set :@_max_per_page, @_max_per_page if defined?(@_max_per_page)
76
+ end
61
77
  end
62
78
  end
63
79
 
@@ -52,7 +52,7 @@ module Kaminari
52
52
  end
53
53
 
54
54
  def max_pages_per(val)
55
- ActiveSupport::Deprecation.warn 'max_pages_per is deprecated. Use max_pages instead.'
55
+ Kaminari.deprecator.warn 'max_pages_per is deprecated. Use max_pages instead.'
56
56
  max_pages val
57
57
  end
58
58
  end
@@ -6,29 +6,31 @@ module Kaminari
6
6
  # Model.page(3).per(10)
7
7
  def per(num, max_per_page: nil)
8
8
  max_per_page ||= ((defined?(@_max_per_page) && @_max_per_page) || self.max_per_page)
9
- @_per = (num || default_per_page).to_i
10
- if (n = num.to_i) < 0 || !(/^\d/ =~ num.to_s)
11
- self
12
- elsif n.zero?
9
+ # ignore a negative or a non-numeric value, and keep the current per value
10
+ return self if (n = num.to_i) < 0 || !(/\A\d/ =~ num.to_s)
11
+
12
+ per_value = n
13
+ if n.zero?
13
14
  limit(n)
14
- elsif max_per_page && (max_per_page < n)
15
- limit(max_per_page).offset(offset_value / limit_value * max_per_page)
16
15
  else
17
- limit(n).offset(offset_value / limit_value * n)
18
- end
16
+ n = max_per_page if max_per_page && (max_per_page < n)
17
+ padding_value = (defined?(@_padding) && @_padding) || 0
18
+ # the current page is unknown after per(0), so go back to the first page
19
+ page_offset = limit_value.zero? ? 0 : (offset_value - padding_value) / limit_value * n
20
+ limit_and_offset n, page_offset + padding_value
21
+ end.tap {|scope| scope.instance_variable_set :@_per, per_value }
19
22
  end
20
23
 
21
24
  def max_paginates_per(new_max_per_page)
22
- @_max_per_page = new_max_per_page
23
-
24
- per (defined?(@_per) && @_per) || default_per_page, max_per_page: new_max_per_page
25
+ per((defined?(@_per) && @_per) || default_per_page, max_per_page: new_max_per_page).tap do |scope|
26
+ scope.instance_variable_set :@_max_per_page, new_max_per_page
27
+ end
25
28
  end
26
29
 
27
30
  def padding(num)
28
31
  num = num.to_i
29
32
  raise ArgumentError, "padding must not be negative" if num < 0
30
- @_padding = num
31
- offset(offset_value + @_padding)
33
+ offset(offset_value + num).tap {|scope| scope.instance_variable_set :@_padding, num }
32
34
  end
33
35
 
34
36
  # Total number of pages
@@ -56,8 +58,8 @@ module Kaminari
56
58
 
57
59
  # Current per-page number
58
60
  def current_per_page
59
- ActiveSupport::Deprecation.warn '#current_per_page is deprecated and will be removed in the next major ' \
60
- 'version. Please use #limit_value instead.'
61
+ Kaminari.deprecator.warn '#current_per_page is deprecated and will be removed in the next major ' \
62
+ 'version. Please use #limit_value instead.'
61
63
 
62
64
  limit_value
63
65
  # (defined?(@_per) && @_per) || default_per_page
@@ -87,5 +89,16 @@ module Kaminari
87
89
  def out_of_range?
88
90
  current_page > total_pages
89
91
  end
92
+
93
+ def paginated?
94
+ limit_value.present?
95
+ end
96
+
97
+ private
98
+
99
+ # Returns another scope with the given limit and offset
100
+ def limit_and_offset(new_limit, new_offset)
101
+ limit(new_limit).offset(new_offset)
102
+ end
90
103
  end
91
104
  end
metadata CHANGED
@@ -1,113 +1,118 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kaminari-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - Akira Matsuda
8
- autorequire:
7
+ - Akira Matsuda
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-12-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '1.13'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '1.13'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '10.0'
41
- description: kaminari-core includes pagination logic independent from ORMs and view
42
- libraries
12
+ - !ruby/object:Gem::Dependency
13
+ name: bundler
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ -
17
+ - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: "1.13"
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ -
25
+ - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: "1.13"
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ -
33
+ - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "10.0"
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ -
41
+ - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "10.0"
44
+ description: kaminari-core includes pagination logic independent from ORMs and view libraries
43
45
  email:
44
- - ronnie@dio.jp
46
+ - ronnie@dio.jp
45
47
  executables: []
46
48
  extensions: []
47
49
  extra_rdoc_files: []
48
50
  files:
49
- - CHANGELOG.md
50
- - MIT-LICENSE
51
- - README.md
52
- - app/views/kaminari/_first_page.html.erb
53
- - app/views/kaminari/_first_page.html.haml
54
- - app/views/kaminari/_first_page.html.slim
55
- - app/views/kaminari/_gap.html.erb
56
- - app/views/kaminari/_gap.html.haml
57
- - app/views/kaminari/_gap.html.slim
58
- - app/views/kaminari/_last_page.html.erb
59
- - app/views/kaminari/_last_page.html.haml
60
- - app/views/kaminari/_last_page.html.slim
61
- - app/views/kaminari/_next_page.html.erb
62
- - app/views/kaminari/_next_page.html.haml
63
- - app/views/kaminari/_next_page.html.slim
64
- - app/views/kaminari/_page.html.erb
65
- - app/views/kaminari/_page.html.haml
66
- - app/views/kaminari/_page.html.slim
67
- - app/views/kaminari/_paginator.html.erb
68
- - app/views/kaminari/_paginator.html.haml
69
- - app/views/kaminari/_paginator.html.slim
70
- - app/views/kaminari/_prev_page.html.erb
71
- - app/views/kaminari/_prev_page.html.haml
72
- - app/views/kaminari/_prev_page.html.slim
73
- - config/locales/kaminari.yml
74
- - kaminari-core.gemspec
75
- - lib/generators/kaminari/config_generator.rb
76
- - lib/generators/kaminari/templates/kaminari_config.rb
77
- - lib/generators/kaminari/views_generator.rb
78
- - lib/kaminari/config.rb
79
- - lib/kaminari/core.rb
80
- - lib/kaminari/core/version.rb
81
- - lib/kaminari/engine.rb
82
- - lib/kaminari/exceptions.rb
83
- - lib/kaminari/helpers/helper_methods.rb
84
- - lib/kaminari/helpers/paginator.rb
85
- - lib/kaminari/helpers/tags.rb
86
- - lib/kaminari/models/array_extension.rb
87
- - lib/kaminari/models/configuration_methods.rb
88
- - lib/kaminari/models/page_scope_methods.rb
89
- - lib/kaminari/railtie.rb
90
- homepage: https://github.com/kaminari/kaminari
51
+ - CHANGELOG.md
52
+ - MIT-LICENSE
53
+ - README.md
54
+ - app/views/kaminari/_first_page.html.erb
55
+ - app/views/kaminari/_first_page.html.haml
56
+ - app/views/kaminari/_first_page.html.slim
57
+ - app/views/kaminari/_gap.html.erb
58
+ - app/views/kaminari/_gap.html.haml
59
+ - app/views/kaminari/_gap.html.slim
60
+ - app/views/kaminari/_last_page.html.erb
61
+ - app/views/kaminari/_last_page.html.haml
62
+ - app/views/kaminari/_last_page.html.slim
63
+ - app/views/kaminari/_next_page.html.erb
64
+ - app/views/kaminari/_next_page.html.haml
65
+ - app/views/kaminari/_next_page.html.slim
66
+ - app/views/kaminari/_page.html.erb
67
+ - app/views/kaminari/_page.html.haml
68
+ - app/views/kaminari/_page.html.slim
69
+ - app/views/kaminari/_paginator.html.erb
70
+ - app/views/kaminari/_paginator.html.haml
71
+ - app/views/kaminari/_paginator.html.slim
72
+ - app/views/kaminari/_prev_page.html.erb
73
+ - app/views/kaminari/_prev_page.html.haml
74
+ - app/views/kaminari/_prev_page.html.slim
75
+ - config/locales/kaminari.yml
76
+ - kaminari-core.gemspec
77
+ - lib/generators/kaminari/config_generator.rb
78
+ - lib/generators/kaminari/templates/kaminari_config.rb
79
+ - lib/generators/kaminari/views_generator.rb
80
+ - lib/kaminari/config.rb
81
+ - lib/kaminari/core.rb
82
+ - lib/kaminari/core/version.rb
83
+ - lib/kaminari/engine.rb
84
+ - lib/kaminari/exceptions.rb
85
+ - lib/kaminari/helpers/helper_methods.rb
86
+ - lib/kaminari/helpers/paginator.rb
87
+ - lib/kaminari/helpers/tags.rb
88
+ - lib/kaminari/models/array_extension.rb
89
+ - lib/kaminari/models/configuration_methods.rb
90
+ - lib/kaminari/models/page_scope_methods.rb
91
+ - lib/kaminari/railtie.rb
92
+ homepage: "https://github.com/kaminari/kaminari"
91
93
  licenses:
92
- - MIT
93
- metadata: {}
94
- post_install_message:
94
+ - MIT
95
+ metadata:
96
+ changelog_uri: "https://github.com/kaminari/kaminari/blob/master/CHANGELOG.md"
97
+ source_code_uri: "https://github.com/kaminari/kaminari/tree/master/kaminari-core"
98
+ rubygems_mfa_required: "true"
95
99
  rdoc_options: []
96
100
  require_paths:
97
- - lib
101
+ - lib
98
102
  required_ruby_version: !ruby/object:Gem::Requirement
99
103
  requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: 2.0.0
104
+ -
105
+ - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 2.0.0
103
108
  required_rubygems_version: !ruby/object:Gem::Requirement
104
109
  requirements:
105
- - - ">="
106
- - !ruby/object:Gem::Version
107
- version: '0'
110
+ -
111
+ - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: "0"
108
114
  requirements: []
109
- rubygems_version: 3.3.0.dev
110
- signing_key:
115
+ rubygems_version: 4.1.0.beta2
111
116
  specification_version: 4
112
117
  summary: Kaminari's core pagination library
113
118
  test_files: []