kaminari 0.17.0 → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kaminari might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.travis.yml +20 -39
- data/CHANGELOG.md +560 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +1 -0
- data/README.md +545 -0
- data/Rakefile +21 -24
- data/gemfiles/active_record_41.gemfile +2 -4
- data/gemfiles/active_record_42.gemfile +2 -4
- data/gemfiles/active_record_50.gemfile +20 -0
- data/gemfiles/active_record_edge.gemfile +5 -6
- data/kaminari.gemspec +11 -17
- data/lib/kaminari.rb +4 -39
- data/lib/kaminari/version.rb +2 -1
- metadata +44 -186
- data/.gemtest +0 -0
- data/.rspec +0 -2
- data/CHANGELOG.rdoc +0 -480
- data/README.rdoc +0 -336
- data/app/views/kaminari/_first_page.html.erb +0 -11
- data/app/views/kaminari/_first_page.html.haml +0 -9
- data/app/views/kaminari/_first_page.html.slim +0 -10
- data/app/views/kaminari/_gap.html.erb +0 -8
- data/app/views/kaminari/_gap.html.haml +0 -8
- data/app/views/kaminari/_gap.html.slim +0 -9
- data/app/views/kaminari/_last_page.html.erb +0 -11
- data/app/views/kaminari/_last_page.html.haml +0 -9
- data/app/views/kaminari/_last_page.html.slim +0 -10
- data/app/views/kaminari/_next_page.html.erb +0 -11
- data/app/views/kaminari/_next_page.html.haml +0 -9
- data/app/views/kaminari/_next_page.html.slim +0 -10
- data/app/views/kaminari/_page.html.erb +0 -12
- data/app/views/kaminari/_page.html.haml +0 -10
- data/app/views/kaminari/_page.html.slim +0 -11
- data/app/views/kaminari/_paginator.html.erb +0 -23
- data/app/views/kaminari/_paginator.html.haml +0 -18
- data/app/views/kaminari/_paginator.html.slim +0 -19
- data/app/views/kaminari/_prev_page.html.erb +0 -11
- data/app/views/kaminari/_prev_page.html.haml +0 -9
- data/app/views/kaminari/_prev_page.html.slim +0 -10
- data/config/locales/kaminari.yml +0 -19
- data/gemfiles/active_record_30.gemfile +0 -28
- data/gemfiles/active_record_31.gemfile +0 -26
- data/gemfiles/active_record_32.gemfile +0 -25
- data/gemfiles/active_record_40.gemfile +0 -26
- data/gemfiles/data_mapper_12.gemfile +0 -32
- data/gemfiles/mongo_mapper.gemfile +0 -25
- data/gemfiles/mongoid_30.gemfile +0 -22
- data/gemfiles/mongoid_31.gemfile +0 -21
- data/gemfiles/mongoid_40.gemfile +0 -19
- data/gemfiles/mongoid_50.gemfile +0 -23
- data/gemfiles/sinatra_13.gemfile +0 -36
- data/gemfiles/sinatra_14.gemfile +0 -33
- data/lib/generators/kaminari/config_generator.rb +0 -16
- data/lib/generators/kaminari/templates/kaminari_config.rb +0 -10
- data/lib/generators/kaminari/views_generator.rb +0 -119
- data/lib/kaminari/config.rb +0 -51
- data/lib/kaminari/engine.rb +0 -4
- data/lib/kaminari/grape.rb +0 -4
- data/lib/kaminari/helpers/action_view_extension.rb +0 -132
- data/lib/kaminari/helpers/paginator.rb +0 -195
- data/lib/kaminari/helpers/sinatra_helpers.rb +0 -176
- data/lib/kaminari/helpers/tags.rb +0 -108
- data/lib/kaminari/hooks.rb +0 -53
- data/lib/kaminari/models/active_record_extension.rb +0 -22
- data/lib/kaminari/models/active_record_model_extension.rb +0 -22
- data/lib/kaminari/models/active_record_relation_methods.rb +0 -42
- data/lib/kaminari/models/array_extension.rb +0 -66
- data/lib/kaminari/models/configuration_methods.rb +0 -48
- data/lib/kaminari/models/data_mapper_collection_methods.rb +0 -19
- data/lib/kaminari/models/data_mapper_extension.rb +0 -51
- data/lib/kaminari/models/mongo_mapper_extension.rb +0 -18
- data/lib/kaminari/models/mongoid_criteria_methods.rb +0 -40
- data/lib/kaminari/models/mongoid_extension.rb +0 -26
- data/lib/kaminari/models/page_scope_methods.rb +0 -73
- data/lib/kaminari/models/plucky_criteria_methods.rb +0 -23
- data/lib/kaminari/railtie.rb +0 -7
- data/lib/kaminari/sinatra.rb +0 -7
- data/spec/config/config_spec.rb +0 -91
- data/spec/fake_app/active_record/config.rb +0 -3
- data/spec/fake_app/active_record/models.rb +0 -65
- data/spec/fake_app/data_mapper/config.rb +0 -1
- data/spec/fake_app/data_mapper/models.rb +0 -27
- data/spec/fake_app/mongo_mapper/config.rb +0 -2
- data/spec/fake_app/mongo_mapper/models.rb +0 -9
- data/spec/fake_app/mongoid/config.rb +0 -20
- data/spec/fake_app/mongoid/models.rb +0 -38
- data/spec/fake_app/rails_app.rb +0 -56
- data/spec/fake_app/sinatra_app.rb +0 -22
- data/spec/fake_app/views/alternative/kaminari/_first_page.html.erb +0 -1
- data/spec/fake_app/views/alternative/kaminari/_paginator.html.erb +0 -3
- data/spec/fake_app/views/kaminari/bootstrap/_page.html.erb +0 -1
- data/spec/fake_app/views/kaminari/bootstrap/_paginator.html.erb +0 -7
- data/spec/fake_gem.rb +0 -20
- data/spec/generators/views_generator_spec.rb +0 -18
- data/spec/helpers/action_view_extension_spec.rb +0 -318
- data/spec/helpers/helpers_spec.rb +0 -144
- data/spec/helpers/sinatra_helpers_spec.rb +0 -223
- data/spec/helpers/tags_spec.rb +0 -140
- data/spec/models/active_record/active_record_relation_methods_spec.rb +0 -77
- data/spec/models/active_record/inherited_spec.rb +0 -9
- data/spec/models/active_record/scopes_spec.rb +0 -265
- data/spec/models/array_spec.rb +0 -172
- data/spec/models/configuration_methods_spec.rb +0 -125
- data/spec/models/data_mapper/data_mapper_spec.rb +0 -205
- data/spec/models/mongo_mapper/mongo_mapper_spec.rb +0 -84
- data/spec/models/mongoid/mongoid_spec.rb +0 -228
- data/spec/requests/users_spec.rb +0 -53
- data/spec/spec_helper.rb +0 -34
- data/spec/spec_helper_for_sinatra.rb +0 -34
- data/spec/support/database_cleaner.rb +0 -19
- data/spec/support/matchers.rb +0 -52
data/gemfiles/sinatra_14.gemfile
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem 'sinatra', '~> 1.4.0'
|
4
|
-
gem 'rspec', '~> 2.14.1'
|
5
|
-
|
6
|
-
gem 'activerecord', '>= 4.0.0', :require => 'active_record'
|
7
|
-
gem 'padrino-helpers', '~> 0.12.0'
|
8
|
-
|
9
|
-
gem 'rack-test', '>= 0'
|
10
|
-
gem 'sinatra-contrib', '~> 1.4.0'
|
11
|
-
|
12
|
-
if RUBY_VERSION == '1.9.3'
|
13
|
-
gem 'mime-types', '2.99'
|
14
|
-
end
|
15
|
-
|
16
|
-
platforms :ruby do
|
17
|
-
if RUBY_VERSION > "2.1.0"
|
18
|
-
gem 'sqlite3'
|
19
|
-
else
|
20
|
-
gem 'sqlite3', '1.3.8'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
platforms :jruby do
|
24
|
-
gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
|
25
|
-
end
|
26
|
-
platforms :rbx do
|
27
|
-
gem 'rubysl', '~> 2.0'
|
28
|
-
gem 'racc'
|
29
|
-
gem 'rubysl-test-unit'
|
30
|
-
gem 'rubinius-developer_tools'
|
31
|
-
end
|
32
|
-
|
33
|
-
gemspec :path => '../'
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Kaminari
|
2
|
-
module Generators
|
3
|
-
class ConfigGenerator < Rails::Generators::Base
|
4
|
-
source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
5
|
-
|
6
|
-
desc <<DESC
|
7
|
-
Description:
|
8
|
-
Copies Kaminari configuration file to your application's initializer directory.
|
9
|
-
DESC
|
10
|
-
|
11
|
-
def copy_config_file
|
12
|
-
template 'kaminari_config.rb', 'config/initializers/kaminari_config.rb'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
module Kaminari
|
2
|
-
module Generators
|
3
|
-
|
4
|
-
class ViewsGenerator < Rails::Generators::NamedBase
|
5
|
-
source_root File.expand_path('../../../../app/views/kaminari', __FILE__)
|
6
|
-
|
7
|
-
class_option :template_engine, :type => :string, :aliases => '-e', :desc => 'Template engine for the views. Available options are "erb", "haml", and "slim".'
|
8
|
-
|
9
|
-
def self.banner #:nodoc:
|
10
|
-
<<-BANNER.chomp
|
11
|
-
rails g kaminari:views THEME [options]
|
12
|
-
|
13
|
-
Copies all paginator partial templates to your application.
|
14
|
-
You can choose a template THEME by specifying one from the list below:
|
15
|
-
|
16
|
-
- default
|
17
|
-
The default one.
|
18
|
-
This one is used internally while you don't override the partials.
|
19
|
-
#{themes.map {|t| " - #{t.name}\n#{t.description}"}.join("\n")}
|
20
|
-
BANNER
|
21
|
-
end
|
22
|
-
|
23
|
-
desc ''
|
24
|
-
def copy_or_fetch #:nodoc:
|
25
|
-
return copy_default_views if file_name == 'default'
|
26
|
-
|
27
|
-
if theme = self.class.themes.detect {|t| t.name == file_name}
|
28
|
-
if download_templates(theme).empty?
|
29
|
-
say %Q[template_engine: #{template_engine} is not available for theme: #{file_name}]
|
30
|
-
end
|
31
|
-
else
|
32
|
-
say %Q[no such theme: #{file_name}\n avaliable themes: #{self.class.themes.map(&:name).join ", "}]
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
def self.themes
|
38
|
-
begin
|
39
|
-
@themes ||= GitHubApiHelper.get_files_in_master.group_by {|fn, _| fn[0...(fn.index('/') || 0)]}.delete_if {|fn, _| fn.blank?}.map do |name, files|
|
40
|
-
Theme.new name, files
|
41
|
-
end
|
42
|
-
rescue SocketError
|
43
|
-
[]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def download_templates(theme)
|
48
|
-
theme.templates_for(template_engine).each do |template|
|
49
|
-
say " downloading #{template.name} from kaminari_themes..."
|
50
|
-
create_file template.name, GitHubApiHelper.get_content_for("#{theme.name}/#{template.name}")
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def copy_default_views
|
55
|
-
filename_pattern = File.join self.class.source_root, "*.html.#{template_engine}"
|
56
|
-
Dir.glob(filename_pattern).map {|f| File.basename f}.each do |f|
|
57
|
-
copy_file f, "app/views/kaminari/#{f}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def template_engine
|
62
|
-
options[:template_engine].try(:to_s).try(:downcase) || 'erb'
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
Template = Struct.new(:name, :sha) do
|
67
|
-
def description?
|
68
|
-
name == 'DESCRIPTION'
|
69
|
-
end
|
70
|
-
|
71
|
-
def view?
|
72
|
-
name =~ /^app\/views\//
|
73
|
-
end
|
74
|
-
|
75
|
-
def engine #:nodoc:
|
76
|
-
File.extname(name).sub /^\./, ''
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class Theme
|
81
|
-
attr_accessor :name
|
82
|
-
def initialize(name, templates) #:nodoc:
|
83
|
-
@name, @templates = name, templates.map {|fn, sha| Template.new fn.sub(/^#{name}\//, ''), sha}
|
84
|
-
end
|
85
|
-
|
86
|
-
def description #:nodoc:
|
87
|
-
file = @templates.detect(&:description?)
|
88
|
-
return "#{' ' * 12}#{name}" unless file
|
89
|
-
GitHubApiHelper.get_content_for("#{@name}/#{file.name}").chomp.gsub(/^/, ' ' * 12)
|
90
|
-
end
|
91
|
-
|
92
|
-
def templates_for(template_engine) #:nodoc:
|
93
|
-
@templates.select {|t| t.engine == template_engine }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
module GitHubApiHelper
|
98
|
-
def get_files_in_master
|
99
|
-
master_tree_sha = open('https://api.github.com/repos/amatsuda/kaminari_themes/git/refs/heads/master') do |json|
|
100
|
-
ActiveSupport::JSON.decode(json.read)['object']['sha']
|
101
|
-
end
|
102
|
-
open('https://api.github.com/repos/amatsuda/kaminari_themes/git/trees/' + master_tree_sha + '?recursive=1') do |json|
|
103
|
-
blobs = ActiveSupport::JSON.decode(json.read)['tree'].find_all {|i| i['type'] == 'blob' }
|
104
|
-
blobs.map do |blob|
|
105
|
-
[blob['path'], blob['sha']]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
module_function :get_files_in_master
|
110
|
-
|
111
|
-
def get_content_for(path)
|
112
|
-
open('https://api.github.com/repos/amatsuda/kaminari_themes/contents/' + path) do |json|
|
113
|
-
Base64.decode64(ActiveSupport::JSON.decode(json.read)['content'])
|
114
|
-
end
|
115
|
-
end
|
116
|
-
module_function :get_content_for
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
data/lib/kaminari/config.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'active_support/configurable'
|
2
|
-
|
3
|
-
module Kaminari
|
4
|
-
# Configures global settings for Kaminari
|
5
|
-
# Kaminari.configure do |config|
|
6
|
-
# config.default_per_page = 10
|
7
|
-
# end
|
8
|
-
def self.configure(&block)
|
9
|
-
yield @config ||= Kaminari::Configuration.new
|
10
|
-
end
|
11
|
-
|
12
|
-
# Global settings for Kaminari
|
13
|
-
def self.config
|
14
|
-
@config
|
15
|
-
end
|
16
|
-
|
17
|
-
# need a Class for 3.0
|
18
|
-
class Configuration #:nodoc:
|
19
|
-
include ActiveSupport::Configurable
|
20
|
-
config_accessor :default_per_page
|
21
|
-
config_accessor :max_per_page
|
22
|
-
config_accessor :window
|
23
|
-
config_accessor :outer_window
|
24
|
-
config_accessor :left
|
25
|
-
config_accessor :right
|
26
|
-
config_accessor :page_method_name
|
27
|
-
config_accessor :max_pages
|
28
|
-
|
29
|
-
def param_name
|
30
|
-
config.param_name.respond_to?(:call) ? config.param_name.call : config.param_name
|
31
|
-
end
|
32
|
-
|
33
|
-
# define param_name writer (copied from AS::Configurable)
|
34
|
-
writer, line = 'def param_name=(value); config.param_name = value; end', __LINE__
|
35
|
-
singleton_class.class_eval writer, __FILE__, line
|
36
|
-
class_eval writer, __FILE__, line
|
37
|
-
end
|
38
|
-
|
39
|
-
# this is ugly. why can't we pass the default value to config_accessor...?
|
40
|
-
configure do |config|
|
41
|
-
config.default_per_page = 25
|
42
|
-
config.max_per_page = nil
|
43
|
-
config.window = 4
|
44
|
-
config.outer_window = 0
|
45
|
-
config.left = 0
|
46
|
-
config.right = 0
|
47
|
-
config.page_method_name = :page
|
48
|
-
config.param_name = :page
|
49
|
-
config.max_pages = nil
|
50
|
-
end
|
51
|
-
end
|
data/lib/kaminari/engine.rb
DELETED
data/lib/kaminari/grape.rb
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
module Kaminari
|
2
|
-
# = Helpers
|
3
|
-
module ActionViewExtension
|
4
|
-
# A helper that renders the pagination links.
|
5
|
-
#
|
6
|
-
# <%= paginate @articles %>
|
7
|
-
#
|
8
|
-
# ==== Options
|
9
|
-
# * <tt>:window</tt> - The "inner window" size (4 by default).
|
10
|
-
# * <tt>:outer_window</tt> - The "outer window" size (0 by default).
|
11
|
-
# * <tt>:left</tt> - The "left outer window" size (0 by default).
|
12
|
-
# * <tt>:right</tt> - The "right outer window" size (0 by default).
|
13
|
-
# * <tt>:params</tt> - url_for parameters for the links (:controller, :action, etc.)
|
14
|
-
# * <tt>:param_name</tt> - parameter name for page number in the links (:page by default)
|
15
|
-
# * <tt>:remote</tt> - Ajax? (false by default)
|
16
|
-
# * <tt>:ANY_OTHER_VALUES</tt> - Any other hash key & values would be directly passed into each tag as :locals value.
|
17
|
-
def paginate(scope, options = {}, &block)
|
18
|
-
options[:total_pages] ||= options[:num_pages] || scope.total_pages
|
19
|
-
|
20
|
-
paginator = Kaminari::Helpers::Paginator.new(self, options.reverse_merge(:current_page => scope.current_page, :per_page => scope.limit_value, :remote => false))
|
21
|
-
paginator.to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
# A simple "Twitter like" pagination link that creates a link to the previous page.
|
25
|
-
#
|
26
|
-
# ==== Examples
|
27
|
-
# Basic usage:
|
28
|
-
#
|
29
|
-
# <%= link_to_previous_page @items, 'Previous Page' %>
|
30
|
-
#
|
31
|
-
# Ajax:
|
32
|
-
#
|
33
|
-
# <%= link_to_previous_page @items, 'Previous Page', :remote => true %>
|
34
|
-
#
|
35
|
-
# By default, it renders nothing if there are no more results on the previous page.
|
36
|
-
# You can customize this output by passing a block.
|
37
|
-
#
|
38
|
-
# <%= link_to_previous_page @users, 'Previous Page' do %>
|
39
|
-
# <span>At the Beginning</span>
|
40
|
-
# <% end %>
|
41
|
-
def link_to_previous_page(scope, name, options = {}, &block)
|
42
|
-
params = options.delete(:params) || {}
|
43
|
-
param_name = options.delete(:param_name) || Kaminari.config.param_name
|
44
|
-
link_to_unless scope.first_page?, name, params.merge(param_name => scope.prev_page), options.reverse_merge(:rel => 'previous') do
|
45
|
-
block.call if block
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# A simple "Twitter like" pagination link that creates a link to the next page.
|
50
|
-
#
|
51
|
-
# ==== Examples
|
52
|
-
# Basic usage:
|
53
|
-
#
|
54
|
-
# <%= link_to_next_page @items, 'Next Page' %>
|
55
|
-
#
|
56
|
-
# Ajax:
|
57
|
-
#
|
58
|
-
# <%= link_to_next_page @items, 'Next Page', :remote => true %>
|
59
|
-
#
|
60
|
-
# By default, it renders nothing if there are no more results on the next page.
|
61
|
-
# You can customize this output by passing a block.
|
62
|
-
#
|
63
|
-
# <%= link_to_next_page @users, 'Next Page' do %>
|
64
|
-
# <span>No More Pages</span>
|
65
|
-
# <% end %>
|
66
|
-
def link_to_next_page(scope, name, options = {}, &block)
|
67
|
-
params = options.delete(:params) || {}
|
68
|
-
param_name = options.delete(:param_name) || Kaminari.config.param_name
|
69
|
-
link_to_unless scope.last_page?, name, params.merge(param_name => scope.next_page), options.reverse_merge(:rel => 'next') do
|
70
|
-
block.call if block
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Renders a helpful message with numbers of displayed vs. total entries.
|
75
|
-
# Ported from mislav/will_paginate
|
76
|
-
#
|
77
|
-
# ==== Examples
|
78
|
-
# Basic usage:
|
79
|
-
#
|
80
|
-
# <%= page_entries_info @posts %>
|
81
|
-
# #-> Displaying posts 6 - 10 of 26 in total
|
82
|
-
#
|
83
|
-
# By default, the message will use the humanized class name of objects
|
84
|
-
# in collection: for instance, "project types" for ProjectType models.
|
85
|
-
# The namespace will be cutted out and only the last name will be used.
|
86
|
-
# Override this with the <tt>:entry_name</tt> parameter:
|
87
|
-
#
|
88
|
-
# <%= page_entries_info @posts, :entry_name => 'item' %>
|
89
|
-
# #-> Displaying items 6 - 10 of 26 in total
|
90
|
-
def page_entries_info(collection, options = {})
|
91
|
-
entry_name = options[:entry_name] || collection.entry_name
|
92
|
-
entry_name = entry_name.pluralize unless collection.total_count == 1
|
93
|
-
|
94
|
-
if collection.total_pages < 2
|
95
|
-
t('helpers.page_entries_info.one_page.display_entries', :entry_name => entry_name, :count => collection.total_count)
|
96
|
-
else
|
97
|
-
first = collection.offset_value + 1
|
98
|
-
last = (sum = collection.offset_value + collection.limit_value) > collection.total_count ? collection.total_count : sum
|
99
|
-
t('helpers.page_entries_info.more_pages.display_entries', :entry_name => entry_name, :first => first, :last => last, :total => collection.total_count)
|
100
|
-
end.html_safe
|
101
|
-
end
|
102
|
-
|
103
|
-
# Renders rel="next" and rel="prev" links to be used in the head.
|
104
|
-
#
|
105
|
-
# ==== Examples
|
106
|
-
# Basic usage:
|
107
|
-
#
|
108
|
-
# In head:
|
109
|
-
# <head>
|
110
|
-
# <title>My Website</title>
|
111
|
-
# <%= yield :head %>
|
112
|
-
# </head>
|
113
|
-
#
|
114
|
-
# Somewhere in body:
|
115
|
-
# <% content_for :head do %>
|
116
|
-
# <%= rel_next_prev_link_tags @items %>
|
117
|
-
# <% end %>
|
118
|
-
#
|
119
|
-
# #-> <link rel="next" href="/items/page/3" /><link rel="prev" href="/items/page/1" />
|
120
|
-
#
|
121
|
-
def rel_next_prev_link_tags(scope, options = {})
|
122
|
-
params = options.delete(:params) || {}
|
123
|
-
param_name = options.delete(:param_name) || Kaminari.config.param_name
|
124
|
-
|
125
|
-
output = ""
|
126
|
-
output << '<link rel="next" href="' + url_for(params.merge(param_name => scope.next_page, :only_path => true)) + '"/>' if scope.next_page
|
127
|
-
output << '<link rel="prev" href="' + url_for(params.merge(param_name => scope.prev_page, :only_path => true)) + '"/>' if scope.prev_page
|
128
|
-
|
129
|
-
output.html_safe
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'active_support/inflector'
|
2
|
-
require 'action_view'
|
3
|
-
require 'action_view/log_subscriber'
|
4
|
-
require 'action_view/context'
|
5
|
-
require 'kaminari/helpers/tags'
|
6
|
-
|
7
|
-
module Kaminari
|
8
|
-
module Helpers
|
9
|
-
# The main container tag
|
10
|
-
class Paginator < Tag
|
11
|
-
# so that this instance can actually "render"
|
12
|
-
include ::ActionView::Context
|
13
|
-
|
14
|
-
def initialize(template, options) #:nodoc:
|
15
|
-
ActiveSupport::Deprecation.warn 'num_pages is deprecated and will be removed in Kaminari 1.0. Please use total_pages instead.' if options.has_key? :num_pages
|
16
|
-
options[:num_pages] ||= options[:total_pages]
|
17
|
-
|
18
|
-
@window_options = {}.tap do |h|
|
19
|
-
h[:window] = options.delete(:window) || options.delete(:inner_window) || Kaminari.config.window
|
20
|
-
outer_window = options.delete(:outer_window) || Kaminari.config.outer_window
|
21
|
-
h[:left] = options.delete(:left) || Kaminari.config.left
|
22
|
-
h[:left] = outer_window if h[:left] == 0
|
23
|
-
h[:right] = options.delete(:right) || Kaminari.config.right
|
24
|
-
h[:right] = outer_window if h[:right] == 0
|
25
|
-
end
|
26
|
-
@template, @options = template, options
|
27
|
-
@theme = @options[:theme]
|
28
|
-
@views_prefix = @options[:views_prefix]
|
29
|
-
@window_options.merge! @options
|
30
|
-
@window_options[:current_page] = @options[:current_page] = PageProxy.new(@window_options, @options[:current_page], nil)
|
31
|
-
|
32
|
-
@last = nil
|
33
|
-
# initialize the output_buffer for Context
|
34
|
-
@output_buffer = ActionView::OutputBuffer.new
|
35
|
-
end
|
36
|
-
|
37
|
-
# render given block as a view template
|
38
|
-
def render(&block)
|
39
|
-
instance_eval(&block) if @options[:total_pages] > 1
|
40
|
-
@output_buffer
|
41
|
-
end
|
42
|
-
|
43
|
-
# enumerate each page providing PageProxy object as the block parameter
|
44
|
-
# Because of performance reason, this doesn't actually enumerate all pages but pages that are seemingly relevant to the paginator.
|
45
|
-
# "Relevant" pages are:
|
46
|
-
# * pages inside the left outer window plus one for showing the gap tag
|
47
|
-
# * pages inside the inner window plus one on the left plus one on the right for showing the gap tags
|
48
|
-
# * pages inside the right outer window plus one for showing the gap tag
|
49
|
-
def each_relevant_page
|
50
|
-
return to_enum(:each_relevant_page) unless block_given?
|
51
|
-
|
52
|
-
relevant_pages(@window_options).each do |page|
|
53
|
-
yield PageProxy.new(@window_options, page, @last)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
alias each_page each_relevant_page
|
57
|
-
|
58
|
-
def relevant_pages(options)
|
59
|
-
left_window_plus_one = 1.upto(options[:left] + 1).to_a
|
60
|
-
right_window_plus_one = (options[:total_pages] - options[:right]).upto(options[:total_pages]).to_a
|
61
|
-
inside_window_plus_each_sides = (options[:current_page] - options[:window] - 1).upto(options[:current_page] + options[:window] + 1).to_a
|
62
|
-
|
63
|
-
(left_window_plus_one + inside_window_plus_each_sides + right_window_plus_one).uniq.sort.reject {|x| (x < 1) || (x > options[:total_pages])}
|
64
|
-
end
|
65
|
-
private :relevant_pages
|
66
|
-
|
67
|
-
def page_tag(page)
|
68
|
-
@last = Page.new @template, @options.merge(:page => page)
|
69
|
-
end
|
70
|
-
|
71
|
-
%w[first_page prev_page next_page last_page gap].each do |tag|
|
72
|
-
eval <<-DEF
|
73
|
-
def #{tag}_tag
|
74
|
-
@last = #{tag.classify}.new @template, @options
|
75
|
-
end
|
76
|
-
DEF
|
77
|
-
end
|
78
|
-
|
79
|
-
def to_s #:nodoc:
|
80
|
-
subscriber = ActionView::LogSubscriber.log_subscribers.detect {|ls| ls.is_a? ActionView::LogSubscriber}
|
81
|
-
|
82
|
-
# There is a logging subscriber
|
83
|
-
# and we don't want it to log render_partial
|
84
|
-
# It is threadsafe, but might not repress logging
|
85
|
-
# consistently in a high-load environment
|
86
|
-
if subscriber
|
87
|
-
unless defined? subscriber.render_partial_with_logging
|
88
|
-
class << subscriber
|
89
|
-
alias_method :render_partial_with_logging, :render_partial
|
90
|
-
attr_accessor :render_without_logging
|
91
|
-
# ugly hack to make a renderer where
|
92
|
-
# we can turn logging on or off
|
93
|
-
def render_partial(event)
|
94
|
-
render_partial_with_logging(event) unless render_without_logging
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
subscriber.render_without_logging = true
|
100
|
-
ret = super @window_options.merge :paginator => self
|
101
|
-
subscriber.render_without_logging = false
|
102
|
-
|
103
|
-
ret
|
104
|
-
else
|
105
|
-
super @window_options.merge :paginator => self
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# delegates view helper methods to @template
|
110
|
-
def method_missing(name, *args, &block)
|
111
|
-
@template.respond_to?(name) ? @template.send(name, *args, &block) : super
|
112
|
-
end
|
113
|
-
private :method_missing
|
114
|
-
|
115
|
-
# Wraps a "page number" and provides some utility methods
|
116
|
-
class PageProxy
|
117
|
-
include Comparable
|
118
|
-
|
119
|
-
def initialize(options, page, last) #:nodoc:
|
120
|
-
@options, @page, @last = options, page, last
|
121
|
-
end
|
122
|
-
|
123
|
-
# the page number
|
124
|
-
def number
|
125
|
-
@page
|
126
|
-
end
|
127
|
-
|
128
|
-
# current page or not
|
129
|
-
def current?
|
130
|
-
@page == @options[:current_page]
|
131
|
-
end
|
132
|
-
|
133
|
-
# the first page or not
|
134
|
-
def first?
|
135
|
-
@page == 1
|
136
|
-
end
|
137
|
-
|
138
|
-
# the last page or not
|
139
|
-
def last?
|
140
|
-
@page == @options[:total_pages]
|
141
|
-
end
|
142
|
-
|
143
|
-
# the previous page or not
|
144
|
-
def prev?
|
145
|
-
@page == @options[:current_page] - 1
|
146
|
-
end
|
147
|
-
|
148
|
-
# the next page or not
|
149
|
-
def next?
|
150
|
-
@page == @options[:current_page] + 1
|
151
|
-
end
|
152
|
-
|
153
|
-
# within the left outer window or not
|
154
|
-
def left_outer?
|
155
|
-
@page <= @options[:left]
|
156
|
-
end
|
157
|
-
|
158
|
-
# within the right outer window or not
|
159
|
-
def right_outer?
|
160
|
-
@options[:total_pages] - @page < @options[:right]
|
161
|
-
end
|
162
|
-
|
163
|
-
# inside the inner window or not
|
164
|
-
def inside_window?
|
165
|
-
(@options[:current_page] - @page).abs <= @options[:window]
|
166
|
-
end
|
167
|
-
|
168
|
-
# The last rendered tag was "truncated" or not
|
169
|
-
def was_truncated?
|
170
|
-
@last.is_a? Gap
|
171
|
-
end
|
172
|
-
|
173
|
-
def to_i
|
174
|
-
number
|
175
|
-
end
|
176
|
-
|
177
|
-
def to_s
|
178
|
-
number.to_s
|
179
|
-
end
|
180
|
-
|
181
|
-
def +(other)
|
182
|
-
to_i + other.to_i
|
183
|
-
end
|
184
|
-
|
185
|
-
def -(other)
|
186
|
-
to_i - other.to_i
|
187
|
-
end
|
188
|
-
|
189
|
-
def <=>(other)
|
190
|
-
to_i <=> other.to_i
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|