kaminari 0.14.1 → 0.15.0
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.document +1 -4
- data/.gitignore +1 -0
- data/.travis.yml +23 -5
- data/CHANGELOG +33 -0
- data/Gemfile +1 -1
- data/README.rdoc +40 -22
- data/Rakefile +2 -2
- data/app/views/kaminari/_first_page.html.erb +1 -1
- data/app/views/kaminari/_first_page.html.haml +1 -1
- data/app/views/kaminari/_first_page.html.slim +1 -1
- data/app/views/kaminari/_gap.html.erb +1 -1
- data/app/views/kaminari/_gap.html.haml +1 -1
- data/app/views/kaminari/_gap.html.slim +1 -1
- data/app/views/kaminari/_last_page.html.erb +1 -1
- data/app/views/kaminari/_last_page.html.haml +1 -1
- data/app/views/kaminari/_last_page.html.slim +1 -1
- data/app/views/kaminari/_next_page.html.erb +1 -1
- data/app/views/kaminari/_next_page.html.haml +1 -1
- data/app/views/kaminari/_next_page.html.slim +1 -1
- data/app/views/kaminari/_prev_page.html.erb +1 -1
- data/app/views/kaminari/_prev_page.html.haml +1 -1
- data/app/views/kaminari/_prev_page.html.slim +1 -1
- data/gemfiles/active_record_30.gemfile +5 -3
- data/gemfiles/active_record_31.gemfile +3 -3
- data/gemfiles/active_record_32.gemfile +6 -3
- data/gemfiles/active_record_40.gemfile +7 -0
- data/gemfiles/active_record_edge.gemfile +11 -0
- data/gemfiles/data_mapper_12.gemfile +10 -7
- data/gemfiles/mongo_mapper.gemfile +4 -1
- data/gemfiles/mongoid_24.gemfile +1 -1
- data/gemfiles/mongoid_30.gemfile +7 -2
- data/gemfiles/mongoid_31.gemfile +12 -0
- data/gemfiles/sinatra_13.gemfile +15 -0
- data/gemfiles/sinatra_14.gemfile +15 -0
- data/kaminari.gemspec +4 -4
- data/lib/kaminari/config.rb +2 -0
- data/lib/kaminari/helpers/action_view_extension.rb +1 -2
- data/lib/kaminari/helpers/paginator.rb +23 -12
- data/lib/kaminari/helpers/sinatra_helpers.rb +7 -1
- data/lib/kaminari/helpers/tags.rb +1 -1
- data/lib/kaminari/models/active_record_model_extension.rb +7 -5
- data/lib/kaminari/models/active_record_relation_methods.rb +12 -10
- data/lib/kaminari/models/array_extension.rb +4 -6
- data/lib/kaminari/models/configuration_methods.rb +16 -2
- data/lib/kaminari/models/data_mapper_extension.rb +5 -2
- data/lib/kaminari/models/page_scope_methods.rb +32 -3
- data/lib/kaminari/models/plucky_criteria_methods.rb +2 -1
- data/lib/kaminari/version.rb +1 -1
- data/lib/kaminari.rb +5 -4
- data/spec/config/config_spec.rb +15 -0
- data/spec/fake_app/active_record/models.rb +8 -0
- data/spec/fake_app/rails_app.rb +1 -0
- data/spec/helpers/action_view_extension_spec.rb +2 -2
- data/spec/models/active_record/active_record_relation_methods_spec.rb +42 -1
- data/spec/models/active_record/scopes_spec.rb +79 -2
- data/spec/models/array_spec.rb +29 -0
- data/spec/models/configuration_methods_spec.rb +125 -0
- data/spec/models/data_mapper/data_mapper_spec.rb +52 -0
- data/spec/models/mongo_mapper/mongo_mapper_spec.rb +12 -0
- data/spec/models/mongoid/mongoid_spec.rb +16 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/spec_helper_for_sinatra.rb +2 -3
- data/spec/support/database_cleaner.rb +5 -2
- metadata +50 -73
- data/gemfiles/sinatra.gemfile +0 -10
- data/spec/models/active_record/default_per_page_spec.rb +0 -32
- data/spec/models/active_record/max_per_page_spec.rb +0 -32
@@ -88,7 +88,7 @@ module Kaminari
|
|
88
88
|
def page_entries_info(collection, options = {})
|
89
89
|
entry_name = if options[:entry_name]
|
90
90
|
options[:entry_name]
|
91
|
-
elsif collection.
|
91
|
+
elsif collection.is_a?(::Kaminari::PaginatableArray)
|
92
92
|
'entry'
|
93
93
|
else
|
94
94
|
if collection.respond_to? :model # DataMapper
|
@@ -146,6 +146,5 @@ module Kaminari
|
|
146
146
|
|
147
147
|
output.html_safe
|
148
148
|
end
|
149
|
-
|
150
149
|
end
|
151
150
|
end
|
@@ -25,6 +25,7 @@ module Kaminari
|
|
25
25
|
@options[:current_page] = PageProxy.new @window_options.merge(@options), @options[:current_page], nil
|
26
26
|
#FIXME for compatibility. remove num_pages at some time in the future
|
27
27
|
@options[:total_pages] ||= @options[:num_pages]
|
28
|
+
@options[:num_pages] ||= @options[:total_pages]
|
28
29
|
@last = nil
|
29
30
|
# initialize the output_buffer for Context
|
30
31
|
@output_buffer = ActionView::OutputBuffer.new
|
@@ -74,22 +75,32 @@ module Kaminari
|
|
74
75
|
|
75
76
|
def to_s #:nodoc:
|
76
77
|
subscriber = ActionView::LogSubscriber.log_subscribers.detect {|ls| ls.is_a? ActionView::LogSubscriber}
|
77
|
-
return super @window_options.merge(@options).merge :paginator => self unless subscriber
|
78
78
|
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
# There is a logging subscriber
|
80
|
+
# and we don't want it to log render_partial
|
81
|
+
# It is threadsafe, but might not repress logging
|
82
|
+
# consistently in a high-load environment
|
83
|
+
if subscriber
|
84
|
+
unless defined? subscriber.render_partial_with_logging
|
85
|
+
class << subscriber
|
86
|
+
alias_method :render_partial_with_logging, :render_partial
|
87
|
+
attr_accessor :render_without_logging
|
88
|
+
# ugly hack to make a renderer where
|
89
|
+
# we can turn logging on or off
|
90
|
+
def render_partial(event)
|
91
|
+
render_partial_with_logging(event) unless render_without_logging
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
85
95
|
|
86
|
-
|
96
|
+
subscriber.render_without_logging = true
|
97
|
+
ret = super @window_options.merge(@options).merge :paginator => self
|
98
|
+
subscriber.render_without_logging = false
|
87
99
|
|
88
|
-
|
89
|
-
|
90
|
-
|
100
|
+
ret
|
101
|
+
else
|
102
|
+
super @window_options.merge(@options).merge :paginator => self
|
91
103
|
end
|
92
|
-
ret
|
93
104
|
end
|
94
105
|
|
95
106
|
# Wraps a "page number" and provides some utility methods
|
@@ -10,6 +10,11 @@ module Kaminari::Helpers
|
|
10
10
|
def registered(app)
|
11
11
|
app.register Padrino::Helpers
|
12
12
|
app.helpers HelperMethods
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def view_paths
|
17
|
+
@app.views
|
13
18
|
end
|
14
19
|
|
15
20
|
alias included registered
|
@@ -31,6 +36,7 @@ module Kaminari::Helpers
|
|
31
36
|
|
32
37
|
def render(*args)
|
33
38
|
base = ActionView::Base.new.tap do |a|
|
39
|
+
a.view_paths << SinatraHelpers.view_paths
|
34
40
|
a.view_paths << File.expand_path('../../../../app/views', __FILE__)
|
35
41
|
end
|
36
42
|
base.render(*args)
|
@@ -125,7 +131,7 @@ end
|
|
125
131
|
|
126
132
|
rescue LoadError
|
127
133
|
|
128
|
-
$stderr.puts "[!]You
|
134
|
+
$stderr.puts "[!]You should install `padrino-helpers' gem if you want to use kaminari's pagination helpers with Sinatra."
|
129
135
|
$stderr.puts "[!]Kaminari::Helpers::SinatraHelper does nothing now..."
|
130
136
|
|
131
137
|
module Kaminari::Helpers
|
@@ -21,7 +21,7 @@ module Kaminari
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def to_s(locals = {}) #:nodoc:
|
24
|
-
@template.render :partial => "kaminari/#{@theme}#{self.class.name.demodulize.underscore}", :locals => @options.merge(locals)
|
24
|
+
@template.render :partial => "kaminari/#{@theme}#{self.class.name.demodulize.underscore}", :locals => @options.merge(locals), :formats => [:html]
|
25
25
|
end
|
26
26
|
|
27
27
|
def page_url_for(page)
|
@@ -6,14 +6,16 @@ module Kaminari
|
|
6
6
|
|
7
7
|
included do
|
8
8
|
self.send(:include, Kaminari::ConfigurationMethods)
|
9
|
+
end
|
9
10
|
|
11
|
+
module ClassMethods
|
10
12
|
# Fetch the values at the specified page number
|
11
13
|
# Model.page(5)
|
12
|
-
|
13
|
-
limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1))
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
define_method(Kaminari.config.page_method_name) do |num = nil|
|
15
|
+
limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1)).extending do
|
16
|
+
include Kaminari::ActiveRecordRelationMethods
|
17
|
+
include Kaminari::PageScopeMethods
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -3,12 +3,12 @@ module Kaminari
|
|
3
3
|
# a workaround for AR 3.0.x that returns 0 for #count when page > 1
|
4
4
|
# if +limit_value+ is specified, load all the records and count them
|
5
5
|
if ActiveRecord::VERSION::STRING < '3.1'
|
6
|
-
def count #:nodoc:
|
7
|
-
limit_value ? length : super
|
6
|
+
def count(column_name = nil, options = {}) #:nodoc:
|
7
|
+
limit_value && !options[:distinct] ? length : super(column_name, options)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def total_count #:nodoc:
|
11
|
+
def total_count(column_name = :all, options = {}) #:nodoc:
|
12
12
|
# #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
|
13
13
|
@total_count ||= begin
|
14
14
|
c = except(:offset, :limit, :order)
|
@@ -16,14 +16,16 @@ module Kaminari
|
|
16
16
|
# Remove includes only if they are irrelevant
|
17
17
|
c = c.except(:includes) unless references_eager_loaded_tables?
|
18
18
|
|
19
|
-
#
|
20
|
-
|
21
|
-
if
|
22
|
-
|
19
|
+
# Rails 4.1 removes the `options` argument from AR::Relation#count
|
20
|
+
args = [column_name]
|
21
|
+
args << options if ActiveRecord::VERSION::STRING < '4.1.0'
|
22
|
+
|
23
|
+
# .group returns an OrderdHash that responds to #count
|
24
|
+
c = c.count(*args)
|
25
|
+
if c.is_a?(Hash) || c.is_a?(ActiveSupport::OrderedHash)
|
26
|
+
c.count
|
23
27
|
else
|
24
|
-
|
25
|
-
c = c.count
|
26
|
-
c.respond_to?(:count) ? c.count : c
|
28
|
+
c.respond_to?(:count) ? c.count(*args) : c
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -11,12 +11,10 @@ module Kaminari
|
|
11
11
|
# * <tt>:offset</tt> - offset
|
12
12
|
# * <tt>:total_count</tt> - total_count
|
13
13
|
def initialize(original_array = [], options = {})
|
14
|
-
@_original_array, @_limit_value, @_offset_value, @_total_count = original_array, (options[:limit] || default_per_page).to_i, options[:offset].to_i, options[:total_count]
|
14
|
+
@_original_array, @_limit_value, @_offset_value, @_total_count, @_padding = original_array, (options[:limit] || default_per_page).to_i, options[:offset].to_i, options[:total_count], options[:padding].to_i
|
15
15
|
|
16
16
|
if options[:limit] && options[:offset]
|
17
|
-
|
18
|
-
include Kaminari::PageScopeMethods
|
19
|
-
end
|
17
|
+
extend Kaminari::PageScopeMethods
|
20
18
|
end
|
21
19
|
|
22
20
|
if options[:total_count]
|
@@ -35,7 +33,7 @@ module Kaminari
|
|
35
33
|
|
36
34
|
# returns another chunk of the original array
|
37
35
|
def limit(num)
|
38
|
-
self.class.new @_original_array, :limit => num, :offset => @_offset_value, :total_count => @_total_count
|
36
|
+
self.class.new @_original_array, :limit => num, :offset => @_offset_value, :total_count => @_total_count, :padding => @_padding
|
39
37
|
end
|
40
38
|
|
41
39
|
# total item numbers of the original array
|
@@ -45,7 +43,7 @@ module Kaminari
|
|
45
43
|
|
46
44
|
# returns another chunk of the original array
|
47
45
|
def offset(num)
|
48
|
-
self.class.new @_original_array, :limit => @_limit_value, :offset => num, :total_count => @_total_count
|
46
|
+
self.class.new @_original_array, :limit => @_limit_value, :offset => num, :total_count => @_total_count, :padding => @_padding
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -13,7 +13,7 @@ module Kaminari
|
|
13
13
|
# This model's default +per_page+ value
|
14
14
|
# returns +default_per_page+ value unless explicitly overridden via <tt>paginates_per</tt>
|
15
15
|
def default_per_page
|
16
|
-
@_default_per_page
|
16
|
+
(defined?(@_default_per_page) && @_default_per_page) || Kaminari.config.default_per_page
|
17
17
|
end
|
18
18
|
|
19
19
|
# Overrides the max +per_page+ value per model
|
@@ -27,7 +27,21 @@ module Kaminari
|
|
27
27
|
# This model's max +per_page+ value
|
28
28
|
# returns +max_per_page+ value unless explicitly overridden via <tt>max_paginates_per</tt>
|
29
29
|
def max_per_page
|
30
|
-
@_max_per_page || Kaminari.config.max_per_page
|
30
|
+
(defined?(@_max_per_page) && @_max_per_page) || Kaminari.config.max_per_page
|
31
|
+
end
|
32
|
+
|
33
|
+
# Overrides the max_pages value per model
|
34
|
+
# class Article < ActiveRecord::Base
|
35
|
+
# max_pages_per 100
|
36
|
+
# end
|
37
|
+
def max_pages_per(val)
|
38
|
+
@_max_pages = val
|
39
|
+
end
|
40
|
+
|
41
|
+
# This model's max_pages value
|
42
|
+
# returns max_pages value unless explicitly overridden via <tt>max_pages_per</tt>
|
43
|
+
def max_pages
|
44
|
+
(defined?(@_max_pages) && @_max_pages) || Kaminari.config.max_pages
|
31
45
|
end
|
32
46
|
end
|
33
47
|
end
|
@@ -5,8 +5,10 @@ module Kaminari
|
|
5
5
|
module Paginatable
|
6
6
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
7
7
|
def #{Kaminari.config.page_method_name}(num = 1)
|
8
|
+
model = self
|
9
|
+
model = self.model if self.is_a? DataMapper::Collection
|
8
10
|
num = [num.to_i, 1].max - 1
|
9
|
-
all(:limit => default_per_page, :offset => default_per_page * num).extend Paginating
|
11
|
+
all(:limit => model.default_per_page, :offset => model.default_per_page * num).extend Paginating
|
10
12
|
end
|
11
13
|
RUBY
|
12
14
|
end
|
@@ -26,9 +28,10 @@ module Kaminari
|
|
26
28
|
module Collection
|
27
29
|
extend ActiveSupport::Concern
|
28
30
|
included do
|
29
|
-
include Kaminari::ConfigurationMethods::ClassMethods
|
30
31
|
include Kaminari::DataMapperCollectionMethods
|
31
32
|
include Paginatable
|
33
|
+
|
34
|
+
delegate :default_per_page, :max_per_page, :max_pages, :to => :model
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
@@ -13,22 +13,46 @@ module Kaminari
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def padding(num)
|
16
|
+
@_padding = num
|
16
17
|
offset(offset_value + num.to_i)
|
17
18
|
end
|
18
19
|
|
19
20
|
# Total number of pages
|
20
21
|
def total_pages
|
21
|
-
|
22
|
+
count_without_padding = total_count
|
23
|
+
count_without_padding -= @_padding if defined?(@_padding) && @_padding
|
24
|
+
count_without_padding = 0 if count_without_padding < 0
|
25
|
+
|
26
|
+
total_pages_count = (count_without_padding.to_f / limit_value).ceil
|
27
|
+
if max_pages.present? && max_pages < total_pages_count
|
28
|
+
max_pages
|
29
|
+
else
|
30
|
+
total_pages_count
|
31
|
+
end
|
22
32
|
end
|
23
33
|
#FIXME for compatibility. remove num_pages at some time in the future
|
24
34
|
alias num_pages total_pages
|
25
35
|
|
26
36
|
# Current page number
|
27
37
|
def current_page
|
28
|
-
|
38
|
+
offset_without_padding = offset_value
|
39
|
+
offset_without_padding -= @_padding if defined?(@_padding) && @_padding
|
40
|
+
offset_without_padding = 0 if offset_without_padding < 0
|
41
|
+
|
42
|
+
(offset_without_padding / limit_value) + 1
|
43
|
+
end
|
44
|
+
|
45
|
+
# Next page number in the collection
|
46
|
+
def next_page
|
47
|
+
current_page + 1 unless last_page?
|
48
|
+
end
|
49
|
+
|
50
|
+
# Previous page number in the collection
|
51
|
+
def prev_page
|
52
|
+
current_page - 1 unless first_page?
|
29
53
|
end
|
30
54
|
|
31
|
-
# First page of the collection
|
55
|
+
# First page of the collection?
|
32
56
|
def first_page?
|
33
57
|
current_page == 1
|
34
58
|
end
|
@@ -37,5 +61,10 @@ module Kaminari
|
|
37
61
|
def last_page?
|
38
62
|
current_page >= total_pages
|
39
63
|
end
|
64
|
+
|
65
|
+
# Out of range of the collection?
|
66
|
+
def out_of_range?
|
67
|
+
current_page > total_pages
|
68
|
+
end
|
40
69
|
end
|
41
70
|
end
|
data/lib/kaminari/version.rb
CHANGED
data/lib/kaminari.rb
CHANGED
@@ -10,15 +10,16 @@ end
|
|
10
10
|
|
11
11
|
$stderr.puts <<-EOC if !defined?(Rails) && !defined?(Sinatra) && !defined?(Grape)
|
12
12
|
warning: no framework detected.
|
13
|
-
|
13
|
+
|
14
|
+
Your Gemfile might not be configured properly.
|
14
15
|
---- e.g. ----
|
15
|
-
|
16
|
+
Rails:
|
16
17
|
gem 'kaminari'
|
17
18
|
|
18
|
-
|
19
|
+
Sinatra/Padrino:
|
19
20
|
gem 'kaminari', :require => 'kaminari/sinatra'
|
20
21
|
|
21
|
-
|
22
|
+
Grape:
|
22
23
|
gem 'kaminari', :require => 'kaminari/grape'
|
23
24
|
|
24
25
|
EOC
|
data/spec/config/config_spec.rb
CHANGED
@@ -73,4 +73,19 @@ describe Kaminari::Configuration do
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
describe 'max_pages' do
|
78
|
+
context 'by default' do
|
79
|
+
its(:max_pages) { should == nil }
|
80
|
+
end
|
81
|
+
context 'configure via config block' do
|
82
|
+
before do
|
83
|
+
Kaminari.configure {|c| c.max_pages = 5}
|
84
|
+
end
|
85
|
+
its(:max_pages) { should == 5 }
|
86
|
+
after do
|
87
|
+
Kaminari.configure {|c| c.max_pages = nil}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
76
91
|
end
|
@@ -42,6 +42,13 @@ class User::Address < ActiveRecord::Base
|
|
42
42
|
belongs_to :user
|
43
43
|
end
|
44
44
|
|
45
|
+
# a class that uses abstract class
|
46
|
+
class Product < ActiveRecord::Base
|
47
|
+
self.abstract_class = true
|
48
|
+
end
|
49
|
+
class Device < Product
|
50
|
+
end
|
51
|
+
|
45
52
|
#migrations
|
46
53
|
class CreateAllTables < ActiveRecord::Migration
|
47
54
|
def self.up
|
@@ -51,6 +58,7 @@ class CreateAllTables < ActiveRecord::Migration
|
|
51
58
|
create_table(:readerships) {|t| t.integer :user_id; t.integer :book_id }
|
52
59
|
create_table(:authorships) {|t| t.integer :user_id; t.integer :book_id }
|
53
60
|
create_table(:user_addresses) {|t| t.string :street; t.integer :user_id }
|
61
|
+
create_table(:devices) {|t| t.string :name; t.integer :age}
|
54
62
|
end
|
55
63
|
end
|
56
64
|
ActiveRecord::Migration.verbose = false
|
data/spec/fake_app/rails_app.rb
CHANGED
@@ -11,6 +11,7 @@ app = Class.new(Rails::Application)
|
|
11
11
|
app.config.secret_token = '3b7cd727ee24e8444053437c36cc66c4'
|
12
12
|
app.config.session_store :cookie_store, :key => '_myapp_session'
|
13
13
|
app.config.active_support.deprecation = :log
|
14
|
+
app.config.eager_load = false
|
14
15
|
# Rais.root
|
15
16
|
app.config.root = File.dirname(__FILE__)
|
16
17
|
Rails.backtrace_cleaner.remove_silencers!
|
@@ -77,7 +77,7 @@ describe 'Kaminari::ActionViewExtension' do
|
|
77
77
|
end
|
78
78
|
context 'having no entries' do
|
79
79
|
subject { helper.page_entries_info @users, :params => {:controller => 'users', :action => 'index'} }
|
80
|
-
it { should == 'No
|
80
|
+
it { should == 'No users found' }
|
81
81
|
|
82
82
|
context 'setting the entry name option to "member"' do
|
83
83
|
subject { helper.page_entries_info @users, :entry_name => 'member', :params => {:controller => 'users', :action => 'index'} }
|
@@ -151,7 +151,7 @@ describe 'Kaminari::ActionViewExtension' do
|
|
151
151
|
end
|
152
152
|
context 'having no entries' do
|
153
153
|
subject { helper.page_entries_info @addresses, :params => {:controller => 'addresses', :action => 'index'} }
|
154
|
-
it { should == 'No
|
154
|
+
it { should == 'No addresses found' }
|
155
155
|
end
|
156
156
|
|
157
157
|
context 'having 1 entry' do
|
@@ -19,10 +19,51 @@ if defined? ActiveRecord
|
|
19
19
|
@author.readers.by_read_count.page(1).total_count.should == @readers.size
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
22
23
|
context "when the scope use conditions on includes" do
|
23
24
|
it "should keep includes and successfully count the results" do
|
24
25
|
# Only @author and @author2 have books titled with the title00x partern
|
25
|
-
|
26
|
+
if ActiveRecord::VERSION::STRING >= "4.1.0"
|
27
|
+
User.includes(:books_authored).references(:books).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
|
28
|
+
else
|
29
|
+
User.includes(:books_authored).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the Relation has custom select clause' do
|
35
|
+
specify do
|
36
|
+
lambda { User.select('*, 1 as one').page(1).total_count }.should_not raise_exception
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when total_count receives options" do
|
41
|
+
it "should return a distinct total count for rails < 4.1" do
|
42
|
+
if ActiveRecord::VERSION::STRING < "4.1.0"
|
43
|
+
User.page(1).total_count(:name, :distinct => true).should == 4
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should ignore the options for rails 4.1+" do
|
48
|
+
if ActiveRecord::VERSION::STRING >= "4.1.0"
|
49
|
+
User.page(1).total_count(:name, :distinct => true).should == 7
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if ActiveRecord::VERSION::STRING < '4.1.0'
|
55
|
+
context 'when count receives options' do
|
56
|
+
it 'should return a distinct set by column for rails < 4.1' do
|
57
|
+
User.page(1).count(:name, :distinct => true).should == 4
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the scope returns an ActiveSupport::OrderedHash" do
|
63
|
+
it "should not throw exception by passing options to count" do
|
64
|
+
lambda {
|
65
|
+
@author.readers.by_read_count.page(1).total_count(:name, :distinct => true)
|
66
|
+
}.should_not raise_exception
|
26
67
|
end
|
27
68
|
end
|
28
69
|
end
|
@@ -15,9 +15,10 @@ if defined? ActiveRecord
|
|
15
15
|
before do
|
16
16
|
1.upto(100) {|i| User.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
|
17
17
|
1.upto(100) {|i| GemDefinedModel.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
|
18
|
+
1.upto(100) {|i| Device.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
|
18
19
|
end
|
19
20
|
|
20
|
-
[User, Admin, GemDefinedModel].each do |model_class|
|
21
|
+
[User, Admin, GemDefinedModel, Device].each do |model_class|
|
21
22
|
context "for #{model_class}" do
|
22
23
|
describe '#page' do
|
23
24
|
context 'page 1' do
|
@@ -58,6 +59,11 @@ if defined? ActiveRecord
|
|
58
59
|
it { should have(5).users }
|
59
60
|
its('first.name') { should == 'user001' }
|
60
61
|
end
|
62
|
+
|
63
|
+
context "page 1 per nil (using default)" do
|
64
|
+
subject { model_class.page(1).per(nil) }
|
65
|
+
it { should have(model_class.default_per_page).users }
|
66
|
+
end
|
61
67
|
end
|
62
68
|
|
63
69
|
describe '#padding' do
|
@@ -66,6 +72,12 @@ if defined? ActiveRecord
|
|
66
72
|
it { should have(5).users }
|
67
73
|
its('first.name') { should == 'user002' }
|
68
74
|
end
|
75
|
+
|
76
|
+
context 'page 19 per 5 padding 5' do
|
77
|
+
subject { model_class.page(19).per(5).padding(5) }
|
78
|
+
its(:current_page) { should == 19 }
|
79
|
+
its(:total_pages) { should == 19 }
|
80
|
+
end
|
69
81
|
end
|
70
82
|
|
71
83
|
describe '#total_pages' do
|
@@ -98,8 +110,32 @@ if defined? ActiveRecord
|
|
98
110
|
subject { model_class.page(5).per('aho') }
|
99
111
|
its(:total_pages) { should == 4 }
|
100
112
|
end
|
101
|
-
end
|
102
113
|
|
114
|
+
context 'with max_pages < total pages count from database' do
|
115
|
+
before { model_class.max_pages_per 3 }
|
116
|
+
subject { model_class.page }
|
117
|
+
its(:total_pages) { should == 3 }
|
118
|
+
after { model_class.max_pages_per nil }
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'with max_pages > total pages count from database' do
|
122
|
+
before { model_class.max_pages_per 11 }
|
123
|
+
subject { model_class.page }
|
124
|
+
its(:total_pages) { should == 4 }
|
125
|
+
after { model_class.max_pages_per nil }
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with max_pages is nil' do
|
129
|
+
before { model_class.max_pages_per nil }
|
130
|
+
subject { model_class.page }
|
131
|
+
its(:total_pages) { should == 4 }
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with per(nil) using default" do
|
135
|
+
subject { model_class.page.per(nil) }
|
136
|
+
its(:total_pages) { should == 4 }
|
137
|
+
end
|
138
|
+
end
|
103
139
|
|
104
140
|
describe '#current_page' do
|
105
141
|
context 'page 1' do
|
@@ -113,6 +149,30 @@ if defined? ActiveRecord
|
|
113
149
|
end
|
114
150
|
end
|
115
151
|
|
152
|
+
describe '#next_page' do
|
153
|
+
context 'page 1' do
|
154
|
+
subject { model_class.page }
|
155
|
+
its(:next_page) { should == 2 }
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'page 5' do
|
159
|
+
subject { model_class.page(5) }
|
160
|
+
its(:next_page) { should be_nil }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe '#prev_page' do
|
165
|
+
context 'page 1' do
|
166
|
+
subject { model_class.page }
|
167
|
+
its(:prev_page) { should be_nil }
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'page 5' do
|
171
|
+
subject { model_class.page(5) }
|
172
|
+
its(:prev_page) { should == 4 }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
116
176
|
describe '#first_page?' do
|
117
177
|
context 'on first page' do
|
118
178
|
subject { model_class.page(1).per(10) }
|
@@ -137,6 +197,23 @@ if defined? ActiveRecord
|
|
137
197
|
end
|
138
198
|
end
|
139
199
|
|
200
|
+
describe '#out_of_range?' do
|
201
|
+
context 'on last page' do
|
202
|
+
subject { model_class.page(10).per(10) }
|
203
|
+
its(:out_of_range?) { should == false }
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'within range' do
|
207
|
+
subject { model_class.page(1).per(10) }
|
208
|
+
its(:out_of_range?) { should == false }
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'out of range' do
|
212
|
+
subject { model_class.page(11).per(10) }
|
213
|
+
its(:out_of_range?) { should == true }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
140
217
|
describe '#count' do
|
141
218
|
context 'page 1' do
|
142
219
|
subject { model_class.page }
|
data/spec/models/array_spec.rb
CHANGED
@@ -86,6 +86,11 @@ describe Kaminari::PaginatableArray do
|
|
86
86
|
subject { array.page(5).per('aho') }
|
87
87
|
its(:total_pages) { should == 4 }
|
88
88
|
end
|
89
|
+
|
90
|
+
context 'per 25, padding 25' do
|
91
|
+
subject { array.page(1).padding(25) }
|
92
|
+
its(:total_pages) { should == 3 }
|
93
|
+
end
|
89
94
|
end
|
90
95
|
|
91
96
|
describe '#current_page' do
|
@@ -100,6 +105,30 @@ describe Kaminari::PaginatableArray do
|
|
100
105
|
end
|
101
106
|
end
|
102
107
|
|
108
|
+
describe '#next_page' do
|
109
|
+
context 'page 1' do
|
110
|
+
subject { array.page }
|
111
|
+
its(:next_page) { should == 2 }
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'page 5' do
|
115
|
+
subject { array.page 5 }
|
116
|
+
its(:next_page) { should be_nil }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#prev_page' do
|
121
|
+
context 'page 1' do
|
122
|
+
subject { array.page }
|
123
|
+
its(:prev_page) { should be_nil }
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'page 5' do
|
127
|
+
subject { array.page 5 }
|
128
|
+
its(:prev_page) { should == 4 }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
103
132
|
describe '#count' do
|
104
133
|
context 'page 1' do
|
105
134
|
subject { array.page }
|