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.

Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.document +1 -4
  4. data/.gitignore +1 -0
  5. data/.travis.yml +23 -5
  6. data/CHANGELOG +33 -0
  7. data/Gemfile +1 -1
  8. data/README.rdoc +40 -22
  9. data/Rakefile +2 -2
  10. data/app/views/kaminari/_first_page.html.erb +1 -1
  11. data/app/views/kaminari/_first_page.html.haml +1 -1
  12. data/app/views/kaminari/_first_page.html.slim +1 -1
  13. data/app/views/kaminari/_gap.html.erb +1 -1
  14. data/app/views/kaminari/_gap.html.haml +1 -1
  15. data/app/views/kaminari/_gap.html.slim +1 -1
  16. data/app/views/kaminari/_last_page.html.erb +1 -1
  17. data/app/views/kaminari/_last_page.html.haml +1 -1
  18. data/app/views/kaminari/_last_page.html.slim +1 -1
  19. data/app/views/kaminari/_next_page.html.erb +1 -1
  20. data/app/views/kaminari/_next_page.html.haml +1 -1
  21. data/app/views/kaminari/_next_page.html.slim +1 -1
  22. data/app/views/kaminari/_prev_page.html.erb +1 -1
  23. data/app/views/kaminari/_prev_page.html.haml +1 -1
  24. data/app/views/kaminari/_prev_page.html.slim +1 -1
  25. data/gemfiles/active_record_30.gemfile +5 -3
  26. data/gemfiles/active_record_31.gemfile +3 -3
  27. data/gemfiles/active_record_32.gemfile +6 -3
  28. data/gemfiles/active_record_40.gemfile +7 -0
  29. data/gemfiles/active_record_edge.gemfile +11 -0
  30. data/gemfiles/data_mapper_12.gemfile +10 -7
  31. data/gemfiles/mongo_mapper.gemfile +4 -1
  32. data/gemfiles/mongoid_24.gemfile +1 -1
  33. data/gemfiles/mongoid_30.gemfile +7 -2
  34. data/gemfiles/mongoid_31.gemfile +12 -0
  35. data/gemfiles/sinatra_13.gemfile +15 -0
  36. data/gemfiles/sinatra_14.gemfile +15 -0
  37. data/kaminari.gemspec +4 -4
  38. data/lib/kaminari/config.rb +2 -0
  39. data/lib/kaminari/helpers/action_view_extension.rb +1 -2
  40. data/lib/kaminari/helpers/paginator.rb +23 -12
  41. data/lib/kaminari/helpers/sinatra_helpers.rb +7 -1
  42. data/lib/kaminari/helpers/tags.rb +1 -1
  43. data/lib/kaminari/models/active_record_model_extension.rb +7 -5
  44. data/lib/kaminari/models/active_record_relation_methods.rb +12 -10
  45. data/lib/kaminari/models/array_extension.rb +4 -6
  46. data/lib/kaminari/models/configuration_methods.rb +16 -2
  47. data/lib/kaminari/models/data_mapper_extension.rb +5 -2
  48. data/lib/kaminari/models/page_scope_methods.rb +32 -3
  49. data/lib/kaminari/models/plucky_criteria_methods.rb +2 -1
  50. data/lib/kaminari/version.rb +1 -1
  51. data/lib/kaminari.rb +5 -4
  52. data/spec/config/config_spec.rb +15 -0
  53. data/spec/fake_app/active_record/models.rb +8 -0
  54. data/spec/fake_app/rails_app.rb +1 -0
  55. data/spec/helpers/action_view_extension_spec.rb +2 -2
  56. data/spec/models/active_record/active_record_relation_methods_spec.rb +42 -1
  57. data/spec/models/active_record/scopes_spec.rb +79 -2
  58. data/spec/models/array_spec.rb +29 -0
  59. data/spec/models/configuration_methods_spec.rb +125 -0
  60. data/spec/models/data_mapper/data_mapper_spec.rb +52 -0
  61. data/spec/models/mongo_mapper/mongo_mapper_spec.rb +12 -0
  62. data/spec/models/mongoid/mongoid_spec.rb +16 -0
  63. data/spec/spec_helper.rb +1 -0
  64. data/spec/spec_helper_for_sinatra.rb +2 -3
  65. data/spec/support/database_cleaner.rb +5 -2
  66. metadata +50 -73
  67. data/gemfiles/sinatra.gemfile +0 -10
  68. data/spec/models/active_record/default_per_page_spec.rb +0 -32
  69. 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.empty? || collection.is_a?(PaginatableArray)
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
- # dirty hack to suppress logging render_partial
80
- class << subscriber
81
- alias_method :render_partial_with_logging, :render_partial
82
- # do nothing
83
- def render_partial(event); end
84
- end
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
- ret = super @window_options.merge(@options).merge :paginator => self
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
- class << subscriber
89
- alias_method :render_partial, :render_partial_with_logging
90
- undef :render_partial_with_logging
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 shold install `padrino-helpers' gem if you want to use kaminari's pagination helpers with Sinatra."
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
- self.scope Kaminari.config.page_method_name, Proc.new {|num|
13
- limit(default_per_page).offset(default_per_page * ([num.to_i, 1].max - 1))
14
- } do
15
- include Kaminari::ActiveRecordRelationMethods
16
- include Kaminari::PageScopeMethods
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
- # a workaround to count the actual model instances on distinct query because count + distinct returns wrong value in some cases. see https://github.com/amatsuda/kaminari/pull/160
20
- uses_distinct_sql_statement = c.to_sql =~ /DISTINCT/i
21
- if uses_distinct_sql_statement
22
- c.length
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
- # .group returns an OrderdHash that responds to #count
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
- class << self
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 ||= Kaminari.config.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
- (total_count.to_f / limit_value).ceil
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
- (offset_value / limit_value) + 1
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
@@ -1,7 +1,8 @@
1
1
  module Kaminari
2
2
  module PluckyCriteriaMethods
3
3
  include Kaminari::PageScopeMethods
4
- include Kaminari::ConfigurationMethods::ClassMethods
4
+
5
+ delegate :default_per_page, :max_per_page, :max_pages, :to => :model
5
6
 
6
7
  def limit_value #:nodoc:
7
8
  options[:limit]
@@ -1,3 +1,3 @@
1
1
  module Kaminari
2
- VERSION = '0.14.1'
2
+ VERSION = '0.15.0'
3
3
  end
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
- would you check out if your Gemfile appropriately configured?
13
+
14
+ Your Gemfile might not be configured properly.
14
15
  ---- e.g. ----
15
- when Rails:
16
+ Rails:
16
17
  gem 'kaminari'
17
18
 
18
- when Sinatra/Padrino:
19
+ Sinatra/Padrino:
19
20
  gem 'kaminari', :require => 'kaminari/sinatra'
20
21
 
21
- when Grape:
22
+ Grape:
22
23
  gem 'kaminari', :require => 'kaminari/grape'
23
24
 
24
25
  EOC
@@ -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
@@ -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 entries found' }
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 entries found' }
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
- User.includes(:books_authored).where("books.title LIKE 'title00%'").page(1).total_count.should == 2
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 }
@@ -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 }