kaminari 0.13.0 → 0.14.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 (87) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +8 -1
  3. data/CHANGELOG +46 -10
  4. data/README.rdoc +14 -3
  5. data/Rakefile +22 -2
  6. data/app/views/kaminari/_first_page.html.erb +1 -1
  7. data/app/views/kaminari/_first_page.html.haml +1 -1
  8. data/app/views/kaminari/_first_page.html.slim +1 -1
  9. data/app/views/kaminari/_gap.html.erb +1 -1
  10. data/app/views/kaminari/_gap.html.haml +1 -1
  11. data/app/views/kaminari/_gap.html.slim +1 -1
  12. data/app/views/kaminari/_last_page.html.erb +1 -1
  13. data/app/views/kaminari/_last_page.html.haml +1 -1
  14. data/app/views/kaminari/_last_page.html.slim +1 -1
  15. data/app/views/kaminari/_next_page.html.erb +1 -1
  16. data/app/views/kaminari/_next_page.html.haml +1 -1
  17. data/app/views/kaminari/_next_page.html.slim +1 -1
  18. data/app/views/kaminari/_page.html.erb +2 -2
  19. data/app/views/kaminari/_page.html.haml +1 -1
  20. data/app/views/kaminari/_page.html.slim +1 -1
  21. data/app/views/kaminari/_paginator.html.erb +1 -1
  22. data/app/views/kaminari/_paginator.html.haml +1 -1
  23. data/app/views/kaminari/_paginator.html.slim +1 -1
  24. data/app/views/kaminari/_prev_page.html.erb +1 -1
  25. data/app/views/kaminari/_prev_page.html.haml +1 -1
  26. data/app/views/kaminari/_prev_page.html.slim +1 -1
  27. data/config/locales/kaminari.yml +9 -0
  28. data/gemfiles/active_record_30.gemfile +7 -0
  29. data/gemfiles/active_record_31.gemfile +7 -0
  30. data/gemfiles/active_record_32.gemfile +7 -0
  31. data/gemfiles/data_mapper_12.gemfile +12 -0
  32. data/gemfiles/mongo_mapper.gemfile +7 -0
  33. data/gemfiles/mongoid_24.gemfile +7 -0
  34. data/gemfiles/mongoid_30.gemfile +7 -0
  35. data/gemfiles/sinatra.gemfile +10 -0
  36. data/kaminari.gemspec +6 -18
  37. data/lib/generators/kaminari/templates/kaminari_config.rb +1 -0
  38. data/lib/kaminari.rb +22 -57
  39. data/lib/kaminari/config.rb +7 -1
  40. data/lib/kaminari/grape.rb +4 -0
  41. data/lib/kaminari/helpers/action_view_extension.rb +84 -13
  42. data/lib/kaminari/helpers/paginator.rb +8 -5
  43. data/lib/kaminari/helpers/sinatra_helpers.rb +25 -6
  44. data/lib/kaminari/helpers/tags.rb +1 -1
  45. data/lib/kaminari/hooks.rb +12 -10
  46. data/lib/kaminari/models/active_record_relation_methods.rb +0 -3
  47. data/lib/kaminari/models/configuration_methods.rb +15 -1
  48. data/lib/kaminari/models/page_scope_methods.rb +6 -2
  49. data/lib/kaminari/models/plucky_criteria_methods.rb +3 -0
  50. data/lib/kaminari/railtie.rb +2 -2
  51. data/lib/kaminari/sinatra.rb +2 -10
  52. data/lib/kaminari/version.rb +1 -1
  53. data/spec/config/config_spec.rb +15 -0
  54. data/spec/fake_app/active_record/config.rb +3 -0
  55. data/spec/{fake_app.rb → fake_app/active_record/models.rb} +7 -34
  56. data/spec/fake_app/data_mapper/config.rb +1 -0
  57. data/spec/fake_app/data_mapper/models.rb +27 -0
  58. data/spec/fake_app/mongo_mapper/config.rb +2 -0
  59. data/spec/fake_app/mongo_mapper/models.rb +9 -0
  60. data/spec/fake_app/mongoid/config.rb +16 -0
  61. data/spec/fake_app/mongoid/models.rb +22 -0
  62. data/spec/fake_app/rails_app.rb +55 -0
  63. data/spec/fake_app/sinatra_app.rb +22 -0
  64. data/spec/fake_gem.rb +0 -2
  65. data/spec/helpers/action_view_extension_spec.rb +192 -45
  66. data/spec/helpers/helpers_spec.rb +8 -8
  67. data/spec/helpers/sinatra_helpers_spec.rb +129 -133
  68. data/spec/helpers/tags_spec.rb +8 -8
  69. data/spec/models/active_record/active_record_relation_methods_spec.rb +30 -0
  70. data/spec/models/active_record/default_per_page_spec.rb +32 -0
  71. data/spec/models/active_record/max_per_page_spec.rb +32 -0
  72. data/spec/models/active_record/scopes_spec.rb +166 -0
  73. data/spec/models/array_spec.rb +7 -7
  74. data/spec/models/data_mapper/data_mapper_spec.rb +155 -0
  75. data/spec/models/mongo_mapper/mongo_mapper_spec.rb +72 -0
  76. data/spec/models/mongoid/mongoid_spec.rb +110 -0
  77. data/spec/requests/users_spec.rb +0 -1
  78. data/spec/spec_helper.rb +20 -18
  79. data/spec/spec_helper_for_sinatra.rb +22 -0
  80. data/spec/support/database_cleaner.rb +4 -1
  81. metadata +93 -141
  82. data/spec/models/active_record_relation_methods_spec.rb +0 -28
  83. data/spec/models/data_mapper_spec.rb +0 -181
  84. data/spec/models/default_per_page_spec.rb +0 -29
  85. data/spec/models/mongo_mapper_spec.rb +0 -82
  86. data/spec/models/mongoid_spec.rb +0 -129
  87. data/spec/models/scopes_spec.rb +0 -163
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ if defined? ActiveRecord
4
+
5
+ describe 'max per_page' do
6
+ describe 'AR::Base' do
7
+ subject { ActiveRecord::Base }
8
+ it { should_not respond_to :max_paginates_per }
9
+ end
10
+
11
+ subject { User.page(0).per(100) }
12
+
13
+ context 'by default' do
14
+ its(:limit_value) { should == 100 }
15
+ end
16
+
17
+ context 'when explicitly set via max_paginates_per' do
18
+ before { User.max_paginates_per 10 }
19
+ its(:limit_value) { should == 10 }
20
+ after { User.max_paginates_per nil }
21
+ end
22
+
23
+ describe "max per_page value's independency per model" do
24
+ context "when User's max per_page was changed" do
25
+ before { User.max_paginates_per 10 }
26
+ subject { Book.page(0).per(100) }
27
+ its(:limit_value) { should == 100 }
28
+ after { User.max_paginates_per nil }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ if defined? ActiveRecord
4
+
5
+ shared_examples_for 'the first page' do
6
+ it { should have(25).users }
7
+ its('first.name') { should == 'user001' }
8
+ end
9
+
10
+ shared_examples_for 'blank page' do
11
+ it { should have(0).users }
12
+ end
13
+
14
+ describe Kaminari::ActiveRecordExtension do
15
+ before do
16
+ 1.upto(100) {|i| User.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
17
+ 1.upto(100) {|i| GemDefinedModel.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
18
+ end
19
+
20
+ [User, Admin, GemDefinedModel].each do |model_class|
21
+ context "for #{model_class}" do
22
+ describe '#page' do
23
+ context 'page 1' do
24
+ subject { model_class.page 1 }
25
+ it_should_behave_like 'the first page'
26
+ end
27
+
28
+ context 'page 2' do
29
+ subject { model_class.page 2 }
30
+ it { should have(25).users }
31
+ its('first.name') { should == 'user026' }
32
+ end
33
+
34
+ context 'page without an argument' do
35
+ subject { model_class.page }
36
+ it_should_behave_like 'the first page'
37
+ end
38
+
39
+ context 'page < 1' do
40
+ subject { model_class.page 0 }
41
+ it_should_behave_like 'the first page'
42
+ end
43
+
44
+ context 'page > max page' do
45
+ subject { model_class.page 5 }
46
+ it_should_behave_like 'blank page'
47
+ end
48
+
49
+ describe 'ensure #order_values is preserved' do
50
+ subject { model_class.order('id').page 1 }
51
+ its('order_values.uniq') { should == ['id'] }
52
+ end
53
+ end
54
+
55
+ describe '#per' do
56
+ context 'page 1 per 5' do
57
+ subject { model_class.page(1).per(5) }
58
+ it { should have(5).users }
59
+ its('first.name') { should == 'user001' }
60
+ end
61
+ end
62
+
63
+ describe '#padding' do
64
+ context 'page 1 per 5 padding 1' do
65
+ subject { model_class.page(1).per(5).padding(1) }
66
+ it { should have(5).users }
67
+ its('first.name') { should == 'user002' }
68
+ end
69
+ end
70
+
71
+ describe '#total_pages' do
72
+ context 'per 25 (default)' do
73
+ subject { model_class.page }
74
+ its(:total_pages) { should == 4 }
75
+ end
76
+
77
+ context 'per 7' do
78
+ subject { model_class.page(2).per(7) }
79
+ its(:total_pages) { should == 15 }
80
+ end
81
+
82
+ context 'per 65536' do
83
+ subject { model_class.page(50).per(65536) }
84
+ its(:total_pages) { should == 1 }
85
+ end
86
+
87
+ context 'per 0 (using default)' do
88
+ subject { model_class.page(50).per(0) }
89
+ its(:total_pages) { should == 4 }
90
+ end
91
+
92
+ context 'per -1 (using default)' do
93
+ subject { model_class.page(5).per(-1) }
94
+ its(:total_pages) { should == 4 }
95
+ end
96
+
97
+ context 'per "String value that can not be converted into Number" (using default)' do
98
+ subject { model_class.page(5).per('aho') }
99
+ its(:total_pages) { should == 4 }
100
+ end
101
+ end
102
+
103
+
104
+ describe '#current_page' do
105
+ context 'page 1' do
106
+ subject { model_class.page }
107
+ its(:current_page) { should == 1 }
108
+ end
109
+
110
+ context 'page 2' do
111
+ subject { model_class.page(2).per 3 }
112
+ its(:current_page) { should == 2 }
113
+ end
114
+ end
115
+
116
+ describe '#first_page?' do
117
+ context 'on first page' do
118
+ subject { model_class.page(1).per(10) }
119
+ its(:first_page?) { should == true }
120
+ end
121
+
122
+ context 'not on first page' do
123
+ subject { model_class.page(5).per(10) }
124
+ its(:first_page?) { should == false }
125
+ end
126
+ end
127
+
128
+ describe '#last_page?' do
129
+ context 'on last page' do
130
+ subject { model_class.page(10).per(10) }
131
+ its(:last_page?) { should == true }
132
+ end
133
+
134
+ context 'not on last page' do
135
+ subject { model_class.page(1).per(10) }
136
+ its(:last_page?) { should == false }
137
+ end
138
+ end
139
+
140
+ describe '#count' do
141
+ context 'page 1' do
142
+ subject { model_class.page }
143
+ its(:count) { should == 25 }
144
+ end
145
+
146
+ context 'page 2' do
147
+ subject { model_class.page 2 }
148
+ its(:count) { should == 25 }
149
+ end
150
+ end
151
+
152
+ context 'chained with .group' do
153
+ subject { model_class.group('age').page(2).per 5 }
154
+ # 0..10
155
+ its(:total_count) { should == 11 }
156
+ its(:total_pages) { should == 3 }
157
+ end
158
+
159
+ context 'activerecord descendants' do
160
+ subject { ActiveRecord::Base.descendants }
161
+ its(:length) { should_not == 0 }
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -56,35 +56,35 @@ describe Kaminari::PaginatableArray do
56
56
  end
57
57
  end
58
58
 
59
- describe '#num_pages' do
59
+ describe '#total_pages' do
60
60
  context 'per 25 (default)' do
61
61
  subject { array.page }
62
- its(:num_pages) { should == 4 }
62
+ its(:total_pages) { should == 4 }
63
63
  end
64
64
 
65
65
  context 'per 7' do
66
66
  subject { array.page(2).per(7) }
67
- its(:num_pages) { should == 15 }
67
+ its(:total_pages) { should == 15 }
68
68
  end
69
69
 
70
70
  context 'per 65536' do
71
71
  subject { array.page(50).per(65536) }
72
- its(:num_pages) { should == 1 }
72
+ its(:total_pages) { should == 1 }
73
73
  end
74
74
 
75
75
  context 'per 0 (using default)' do
76
76
  subject { array.page(50).per(0) }
77
- its(:num_pages) { should == 4 }
77
+ its(:total_pages) { should == 4 }
78
78
  end
79
79
 
80
80
  context 'per -1 (using default)' do
81
81
  subject { array.page(5).per(-1) }
82
- its(:num_pages) { should == 4 }
82
+ its(:total_pages) { should == 4 }
83
83
  end
84
84
 
85
85
  context 'per "String value that can not be converted into Number" (using default)' do
86
86
  subject { array.page(5).per('aho') }
87
- its(:num_pages) { should == 4 }
87
+ its(:total_pages) { should == 4 }
88
88
  end
89
89
  end
90
90
 
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ if defined? DataMapper
4
+ describe Kaminari::DataMapperExtension do
5
+ before do
6
+ 100.times do |i|
7
+ User.create(:name => "User#{i}", :age => i)
8
+ end
9
+
10
+ worker0 = User[0]
11
+ 50.times do |i|
12
+ worker0.projects << Project.create(:name => "Project#{i}")
13
+ end
14
+ worker0.projects.save
15
+ end
16
+
17
+ describe 'Collection' do
18
+ subject{ User.all }
19
+ it { should respond_to(:page) }
20
+ it { should_not respond_to(:per) }
21
+ end
22
+
23
+ describe 'Model' do
24
+ subject{ User }
25
+ it { should respond_to(:page) }
26
+ it { should respond_to(:default_per_page) }
27
+ it { should_not respond_to(:per) }
28
+ end
29
+
30
+ describe '#page' do
31
+ context 'page 0' do
32
+ subject { User.all(:age.gte => 60).page 0 }
33
+ it { should be_a DataMapper::Collection }
34
+ its(:current_page) { should == 1 }
35
+ its('query.limit') { should == 25 }
36
+ its('query.offset') { should == 0 }
37
+ its(:total_count) { should == User.count(:age.gte => 60) }
38
+ its(:total_pages) { should == 2 }
39
+ end
40
+
41
+ context 'page 1' do
42
+ subject { User.all(:age.gte => 0).page 1 }
43
+ it { should be_a DataMapper::Collection }
44
+ its(:current_page) { should == 1 }
45
+ its('query.limit') { should == 25 }
46
+ its('query.offset') { should == 0 }
47
+ its(:total_count) { should == 100 }
48
+ its(:total_pages) { should == 4 }
49
+ end
50
+
51
+ context 'page 2' do
52
+ subject { User.page 2 }
53
+ it { should be_a DataMapper::Collection }
54
+ its(:current_page) { should == 2 }
55
+ its(:limit_value) { should == 25 }
56
+ its('query.limit') { should == 25 }
57
+ its('query.offset') { should == 25 }
58
+ its(:total_count) { should == 100 }
59
+ its(:total_pages) { should == 4 }
60
+ end
61
+
62
+ context 'page "foobar"' do
63
+ subject { User.page 'foobar' }
64
+ it { should be_a DataMapper::Collection }
65
+ its(:current_page) { should == 1 }
66
+ its('query.limit') { should == 25 }
67
+ its('query.offset') { should == 0 }
68
+ its(:total_count) { should == 100 }
69
+ its(:total_pages) { should == 4 }
70
+ end
71
+
72
+ context 'with criteria before' do
73
+ subject { User.all(:age.gt => 60).page 2 }
74
+ it { should be_a DataMapper::Collection }
75
+ its(:current_page) { should == 2 }
76
+ its('query.limit') { should == 25 }
77
+ its('query.offset') { should == 25 }
78
+ its(:total_count) { should == User.count(:age.gt => 60) }
79
+ its(:total_pages) { should == 2 }
80
+ end
81
+
82
+ context 'with criteria after' do
83
+ subject { User.page(2).all(:age.gt => 60) }
84
+ it { should be_a DataMapper::Collection }
85
+ its(:current_page) { should == 2 }
86
+ its('query.limit') { should == 25 }
87
+ its('query.offset') { should == 25 }
88
+ its(:total_count) { should == User.count(:age.gt => 60) }
89
+ its(:total_pages) { should == 2 }
90
+ end
91
+ end
92
+
93
+ describe '#per' do
94
+ context 'on simple query' do
95
+ subject { User.page(2).per(20) }
96
+ it { should be_a DataMapper::Collection }
97
+ its(:current_page) { should == 2 }
98
+ its('query.limit') { should == 20 }
99
+ its(:limit_value) { should == 20 }
100
+ its('query.offset') { should == 20 }
101
+ its(:total_count) { should == 100 }
102
+ its(:total_pages) { should == 5 }
103
+ end
104
+
105
+ context 'on query with condition' do
106
+ subject { User.page(5).all(:age.lte => 80).per(13) }
107
+ its(:current_page) { should == 5 }
108
+ its('query.limit') { should == 13 }
109
+ its('query.offset') { should == 52 }
110
+ its(:total_count) { should == 81 }
111
+ its(:total_pages) { should == 7 }
112
+ end
113
+
114
+ context 'on query with order' do
115
+ subject { User.page(5).all(:age.lte => 80, :order => [:age.asc]).per(13) }
116
+ it('includes user with age 52') { should include(User.first(:age => 52)) }
117
+ it('does not include user with age 51') { should_not include(User.first(:age => 51)) }
118
+ it('includes user with age 52') { should include(User.first(:age => 64)) }
119
+ it('does not include user with age 51') { should_not include(User.first(:age => 65)) }
120
+ its(:current_page) { should == 5 }
121
+ its('query.limit') { should == 13 }
122
+ its('query.offset') { should == 52 }
123
+ its(:total_count) { should == 81 }
124
+ its(:total_pages) { should == 7 }
125
+ end
126
+
127
+ context 'on chained queries' do
128
+ subject { User.all(:age.gte => 50).page(3).all(:age.lte => 80).per(13) }
129
+ its(:current_page) { should == 3 }
130
+ its('query.limit') { should == 13 }
131
+ its('query.offset') { should == 26 }
132
+ its(:total_count) { should == 31 }
133
+ its(:total_pages) { should == 3 }
134
+ end
135
+
136
+ context 'on query on association' do
137
+ subject { User[0].projects.page(3).all(:name.like => 'Project%').per(5) }
138
+ its(:current_page) { should == 3 }
139
+ its('query.limit') { should == 5 }
140
+ its('query.offset') { should == 10 }
141
+ its(:total_count) { should == 50 }
142
+ its(:total_pages) { should == 10 }
143
+ end
144
+
145
+ context 'on query with association conditions' do
146
+ subject { User.page(3).all(:projects => Project.all).per(5) }
147
+ its(:current_page) { should == 3 }
148
+ its('query.limit') { should == 5 }
149
+ its('query.offset') { should == 10 }
150
+ its(:total_count) { should == 50 }
151
+ its(:total_pages) { should == 10 }
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ if defined? MongoMapper
4
+ describe Kaminari::MongoMapperExtension do
5
+ before(:each) do
6
+ User.destroy_all
7
+ 41.times { User.create!({:salary => 1}) }
8
+ end
9
+
10
+ describe '#page' do
11
+ context 'page 1' do
12
+ subject { User.page(1) }
13
+ it { should be_a Plucky::Query }
14
+ its(:current_page) { should == 1 }
15
+ its(:limit_value) { should == 25 }
16
+ its(:total_pages) { should == 2 }
17
+ it { should skip(0) }
18
+ end
19
+
20
+ context 'page 2' do
21
+ subject { User.page 2 }
22
+ it { should be_a Plucky::Query }
23
+ its(:current_page) { should == 2 }
24
+ its(:limit_value) { should == 25 }
25
+ its(:total_pages) { should == 2 }
26
+ it { should skip 25 }
27
+ end
28
+
29
+ context 'page "foobar"' do
30
+ subject { User.page 'foobar' }
31
+ it { should be_a Plucky::Query }
32
+ its(:current_page) { should == 1 }
33
+ its(:limit_value) { should == 25 }
34
+ its(:total_pages) { should == 2 }
35
+ it { should skip 0 }
36
+ end
37
+
38
+ context 'with criteria before' do
39
+ it "should have the proper criteria source" do
40
+ User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
41
+ end
42
+
43
+ subject { User.where(:salary => 1).page 2 }
44
+ its(:current_page) { should == 2 }
45
+ its(:limit_value) { should == 25 }
46
+ its(:total_pages) { should == 2 }
47
+ it { should skip 25 }
48
+ end
49
+
50
+ context 'with criteria after' do
51
+ it "should have the proper criteria source" do
52
+ User.where(:salary => 1).page(2).criteria.source.should == {:salary => 1}
53
+ end
54
+
55
+ subject { User.page(2).where(:salary => 1) }
56
+ its(:current_page) { should == 2 }
57
+ its(:limit_value) { should == 25 }
58
+ its(:total_pages) { should == 2 }
59
+ it { should skip 25 }
60
+ end
61
+ end
62
+
63
+ describe '#per' do
64
+ subject { User.page(2).per(10) }
65
+ it { should be_a Plucky::Query }
66
+ its(:current_page) { should == 2 }
67
+ its(:limit_value) { should == 10 }
68
+ its(:total_pages) { should == 5 }
69
+ it { should skip 10 }
70
+ end
71
+ end
72
+ end