will_paginate 2.3.17 → 3.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of will_paginate might be problematic. Click here for more details.

Files changed (83) hide show
  1. data/CHANGELOG.rdoc +24 -80
  2. data/LICENSE +1 -1
  3. data/README.rdoc +125 -0
  4. data/Rakefile +26 -22
  5. data/lib/will_paginate.rb +10 -84
  6. data/lib/will_paginate/array.rb +25 -8
  7. data/lib/will_paginate/collection.rb +15 -28
  8. data/lib/will_paginate/core_ext.rb +26 -0
  9. data/lib/will_paginate/deprecation.rb +50 -0
  10. data/lib/will_paginate/finders.rb +9 -0
  11. data/lib/will_paginate/finders/active_record.rb +158 -0
  12. data/lib/will_paginate/finders/active_resource.rb +51 -0
  13. data/lib/will_paginate/finders/base.rb +112 -0
  14. data/lib/will_paginate/finders/data_mapper.rb +30 -0
  15. data/lib/will_paginate/finders/sequel.rb +23 -0
  16. data/lib/will_paginate/railtie.rb +26 -0
  17. data/lib/will_paginate/version.rb +5 -5
  18. data/lib/will_paginate/view_helpers.rb +25 -436
  19. data/lib/will_paginate/view_helpers/action_view.rb +142 -0
  20. data/lib/will_paginate/view_helpers/base.rb +126 -0
  21. data/lib/will_paginate/view_helpers/link_renderer.rb +130 -0
  22. data/lib/will_paginate/view_helpers/link_renderer_base.rb +83 -0
  23. data/lib/will_paginate/view_helpers/merb.rb +13 -0
  24. data/spec/collection_spec.rb +147 -0
  25. data/spec/console +8 -0
  26. data/spec/console_fixtures.rb +8 -0
  27. data/spec/database.yml +22 -0
  28. data/spec/finders/active_record_spec.rb +377 -0
  29. data/spec/finders/active_resource_spec.rb +52 -0
  30. data/spec/finders/activerecord_test_connector.rb +114 -0
  31. data/spec/finders/data_mapper_spec.rb +62 -0
  32. data/spec/finders/data_mapper_test_connector.rb +20 -0
  33. data/spec/finders/sequel_spec.rb +53 -0
  34. data/spec/finders/sequel_test_connector.rb +9 -0
  35. data/spec/finders_spec.rb +76 -0
  36. data/{test → spec}/fixtures/admin.rb +0 -0
  37. data/{test → spec}/fixtures/developer.rb +2 -3
  38. data/{test → spec}/fixtures/developers_projects.yml +0 -0
  39. data/{test → spec}/fixtures/project.rb +2 -6
  40. data/{test → spec}/fixtures/projects.yml +1 -1
  41. data/{test → spec}/fixtures/replies.yml +0 -0
  42. data/{test → spec}/fixtures/reply.rb +1 -1
  43. data/{test → spec}/fixtures/schema.rb +0 -0
  44. data/spec/fixtures/topic.rb +7 -0
  45. data/{test → spec}/fixtures/topics.yml +0 -0
  46. data/{test → spec}/fixtures/user.rb +0 -0
  47. data/{test → spec}/fixtures/users.yml +0 -0
  48. data/spec/rcov.opts +2 -0
  49. data/spec/spec.opts +2 -0
  50. data/spec/spec_helper.rb +74 -0
  51. data/spec/tasks.rake +60 -0
  52. data/spec/view_helpers/action_view_spec.rb +345 -0
  53. data/spec/view_helpers/base_spec.rb +64 -0
  54. data/spec/view_helpers/link_renderer_base_spec.rb +84 -0
  55. data/spec/view_helpers/view_example_group.rb +103 -0
  56. metadata +60 -65
  57. data/README.md +0 -53
  58. data/lib/will_paginate/finder.rb +0 -269
  59. data/lib/will_paginate/i18n.rb +0 -29
  60. data/lib/will_paginate/locale/en.yml +0 -33
  61. data/lib/will_paginate/named_scope.rb +0 -170
  62. data/lib/will_paginate/named_scope_patch.rb +0 -37
  63. data/lib/will_paginate/per_page.rb +0 -27
  64. data/test/ci.rb +0 -60
  65. data/test/collection_test.rb +0 -160
  66. data/test/console +0 -8
  67. data/test/database.yml +0 -16
  68. data/test/finder_test.rb +0 -527
  69. data/test/fixtures/topic.rb +0 -12
  70. data/test/gemfiles/Gemfile.1.2 +0 -13
  71. data/test/gemfiles/Gemfile.1.2.lock +0 -39
  72. data/test/gemfiles/Gemfile.2.0 +0 -16
  73. data/test/gemfiles/Gemfile.2.0.lock +0 -28
  74. data/test/gemfiles/Gemfile.2.1 +0 -16
  75. data/test/gemfiles/Gemfile.2.1.lock +0 -28
  76. data/test/gemfiles/Gemfile.2.2 +0 -16
  77. data/test/gemfiles/Gemfile.2.2.lock +0 -28
  78. data/test/helper.rb +0 -34
  79. data/test/lib/activerecord_test_case.rb +0 -38
  80. data/test/lib/activerecord_test_connector.rb +0 -86
  81. data/test/lib/load_fixtures.rb +0 -12
  82. data/test/lib/view_test_process.rb +0 -186
  83. data/test/view_test.rb +0 -380
File without changes
@@ -0,0 +1,7 @@
1
+ class Topic < ActiveRecord::Base
2
+ has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
3
+ belongs_to :project
4
+
5
+ scope :mentions_activerecord, :conditions => ['topics.title LIKE ?', '%ActiveRecord%']
6
+ scope :distinct, :select => "DISTINCT #{table_name}.*"
7
+ end
File without changes
File without changes
File without changes
data/spec/rcov.opts ADDED
@@ -0,0 +1,2 @@
1
+ --exclude ^\/,^spec\/,core_ext.rb,deprecation.rb
2
+ --no-validator-links
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --reverse
@@ -0,0 +1,74 @@
1
+ require 'spec/autorun'
2
+
3
+ module MyExtras
4
+ protected
5
+
6
+ def include_phrase(string)
7
+ PhraseMatcher.new(string)
8
+ end
9
+
10
+ def collection(params = {})
11
+ if params[:total_pages]
12
+ params[:per_page] = 1
13
+ params[:total_entries] = params[:total_pages]
14
+ end
15
+ WillPaginate::Collection.new(params[:page] || 1, params[:per_page] || 30, params[:total_entries])
16
+ end
17
+
18
+ def have_deprecation
19
+ DeprecationMatcher.new
20
+ end
21
+ end
22
+
23
+ Spec::Runner.configure do |config|
24
+ # config.include My::Pony, My::Horse, :type => :farm
25
+ config.include MyExtras
26
+ # config.predicate_matchers[:swim] = :can_swim?
27
+
28
+ config.mock_with :mocha
29
+ end
30
+
31
+ class PhraseMatcher
32
+ def initialize(string)
33
+ @string = string
34
+ @pattern = /\b#{string}\b/
35
+ end
36
+
37
+ def matches?(actual)
38
+ @actual = actual.to_s
39
+ @actual =~ @pattern
40
+ end
41
+
42
+ def failure_message
43
+ "expected #{@actual.inspect} to contain phrase #{@string.inspect}"
44
+ end
45
+
46
+ def negative_failure_message
47
+ "expected #{@actual.inspect} not to contain phrase #{@string.inspect}"
48
+ end
49
+ end
50
+
51
+ class DeprecationMatcher
52
+ def initialize
53
+ @old_behavior = WillPaginate::Deprecation.behavior
54
+ @messages = []
55
+ WillPaginate::Deprecation.behavior = lambda { |message, callstack|
56
+ @messages << message
57
+ }
58
+ end
59
+
60
+ def matches?(block)
61
+ block.call
62
+ !@messages.empty?
63
+ ensure
64
+ WillPaginate::Deprecation.behavior = @old_behavior
65
+ end
66
+
67
+ def failure_message
68
+ "expected block to raise a deprecation warning"
69
+ end
70
+
71
+ def negative_failure_message
72
+ "expected block not to raise deprecation warnings, #{@messages.size} raised"
73
+ end
74
+ end
data/spec/tasks.rake ADDED
@@ -0,0 +1,60 @@
1
+ require 'spec/rake/spectask'
2
+
3
+ spec_opts = 'spec/spec.opts'
4
+
5
+ desc 'Run framework-agnostic specs'
6
+ Spec::Rake::SpecTask.new(:spec) do |t|
7
+ t.libs << 'spec'
8
+ t.spec_opts = ['--options', spec_opts]
9
+ t.spec_files = FileList.new('spec/**/*_spec.rb') do |files|
10
+ files.exclude(/\b(active_record|active_resource|action_view|data_mapper|sequel)_/)
11
+ end
12
+ end
13
+
14
+ namespace :spec do
15
+ desc 'Run specs for core, ActiveRecord and ActionView'
16
+ Spec::Rake::SpecTask.new(:rails) do |t|
17
+ t.libs << 'spec'
18
+ t.spec_opts = ['--options', spec_opts]
19
+ t.spec_files = FileList.new('spec/**/*_spec.rb') do |files|
20
+ files.exclude(/\b(data_mapper|sequel)_/)
21
+ end
22
+ end
23
+
24
+ desc 'Run specs for DataMapper'
25
+ Spec::Rake::SpecTask.new(:datamapper) do |t|
26
+ t.libs << 'spec'
27
+ t.spec_opts = ['--options', spec_opts]
28
+ t.spec_files = FileList.new('spec/finders_spec.rb', 'spec/finders/data_mapper_spec.rb')
29
+ end
30
+
31
+ desc 'Run specs for Sequel'
32
+ Spec::Rake::SpecTask.new(:sequel) do |t|
33
+ t.libs << 'spec'
34
+ t.spec_opts = ['--options', spec_opts]
35
+ t.spec_files = FileList.new('spec/finders_spec.rb', 'spec/finders/sequel_spec.rb')
36
+ end
37
+
38
+ desc 'Analyze spec coverage with RCov'
39
+ Spec::Rake::SpecTask.new(:rcov) do |t|
40
+ t.libs << 'spec'
41
+ t.spec_opts = ['--options', spec_opts]
42
+ t.rcov = true
43
+ t.rcov_opts = lambda do
44
+ IO.readlines('spec/rcov.opts').map { |l| l.chomp.split(" ") }.flatten
45
+ end
46
+ end
47
+
48
+ desc 'Print Specdoc for all specs'
49
+ Spec::Rake::SpecTask.new(:doc) do |t|
50
+ t.libs << 'spec'
51
+ t.spec_opts = ['--format', 'specdoc', '--dry-run']
52
+ end
53
+
54
+ desc 'Generate HTML report'
55
+ Spec::Rake::SpecTask.new(:html) do |t|
56
+ t.libs << 'spec'
57
+ t.spec_opts = ['--format', 'html:doc/spec_results.html', '--diff']
58
+ t.fail_on_error = false
59
+ end
60
+ end
@@ -0,0 +1,345 @@
1
+ require 'spec_helper'
2
+ require 'active_support/rescuable' # needed for Ruby 1.9.1
3
+ require 'action_controller'
4
+ require 'view_helpers/view_example_group'
5
+ require 'will_paginate/view_helpers/action_view'
6
+ require 'will_paginate/collection'
7
+
8
+ ActionController::Routing::Routes.draw do |map|
9
+ map.connect 'dummy/page/:page', :controller => 'dummy'
10
+ map.connect 'dummy/dots/page.:page', :controller => 'dummy', :action => 'dots'
11
+ map.connect 'ibocorp/:page', :controller => 'ibocorp',
12
+ :requirements => { :page => /\d+/ },
13
+ :defaults => { :page => 1 }
14
+
15
+ map.connect ':controller/:action/:id'
16
+ end
17
+
18
+ describe WillPaginate::ViewHelpers::ActionView do
19
+ before(:each) do
20
+ @assigns = {}
21
+ @controller = DummyController.new
22
+ @request = @controller.request
23
+ @template = '<%= will_paginate collection, options %>'
24
+ end
25
+
26
+ attr_reader :assigns, :controller, :request
27
+
28
+ def render(locals)
29
+ @view = ActionView::Base.new([], @assigns, @controller)
30
+ @view.request = @request
31
+ @view.render(:inline => @template, :locals => locals)
32
+ end
33
+
34
+ ## basic pagination ##
35
+
36
+ it "should render" do
37
+ paginate do |pagination|
38
+ assert_select 'a[href]', 3 do |elements|
39
+ validate_page_numbers [2,3,2], elements
40
+ assert_select elements.last, ':last-child', "Next &#8594;"
41
+ end
42
+ assert_select 'span', 1
43
+ assert_select 'span.disabled:first-child', '&#8592; Previous'
44
+ assert_select 'em', '1'
45
+ pagination.first.inner_text.should == '&#8592; Previous 1 2 3 Next &#8594;'
46
+ end
47
+ end
48
+
49
+ it "should render nothing when there is only 1 page" do
50
+ paginate(:per_page => 30).should be_empty
51
+ end
52
+
53
+ it "should paginate with options" do
54
+ paginate({ :page => 2 }, :class => 'will_paginate', :previous_label => 'Prev', :next_label => 'Next') do
55
+ assert_select 'a[href]', 4 do |elements|
56
+ validate_page_numbers [1,1,3,3], elements
57
+ # test rel attribute values:
58
+ assert_select elements[1], 'a', '1' do |link|
59
+ link.first['rel'].should == 'prev start'
60
+ end
61
+ assert_select elements.first, 'a', "Prev" do |link|
62
+ link.first['rel'].should == 'prev start'
63
+ end
64
+ assert_select elements.last, 'a', "Next" do |link|
65
+ link.first['rel'].should == 'next'
66
+ end
67
+ end
68
+ assert_select 'em', '2'
69
+ end
70
+ end
71
+
72
+ it "should paginate using a custom renderer class" do
73
+ paginate({}, :renderer => AdditionalLinkAttributesRenderer) do
74
+ assert_select 'a[default=true]', 3
75
+ end
76
+ end
77
+
78
+ it "should paginate using a custom renderer instance" do
79
+ renderer = WillPaginate::ViewHelpers::LinkRenderer.new
80
+ def renderer.gap() '<span class="my-gap">~~</span>' end
81
+
82
+ paginate({ :per_page => 2 }, :inner_window => 0, :outer_window => 0, :renderer => renderer) do
83
+ assert_select 'span.my-gap', '~~'
84
+ end
85
+
86
+ renderer = AdditionalLinkAttributesRenderer.new(:title => 'rendered')
87
+ paginate({}, :renderer => renderer) do
88
+ assert_select 'a[title=rendered]', 3
89
+ end
90
+ end
91
+
92
+ it "should have classnames on previous/next links" do
93
+ paginate do |pagination|
94
+ assert_select 'span.disabled.previous_page:first-child'
95
+ assert_select 'a.next_page[href]:last-child'
96
+ end
97
+ end
98
+
99
+ it "should warn about :prev_label being deprecated" do
100
+ lambda {
101
+ paginate({ :page => 2 }, :prev_label => 'Deprecated') do
102
+ assert_select 'a[href]:first-child', 'Deprecated'
103
+ end
104
+ }.should have_deprecation
105
+ end
106
+
107
+ it "should match expected markup" do
108
+ paginate
109
+ expected = <<-HTML
110
+ <div class="pagination"><span class="previous_page disabled">&#8592; Previous</span>
111
+ <em>1</em>
112
+ <a href="/foo/bar?page=2" rel="next">2</a>
113
+ <a href="/foo/bar?page=3">3</a>
114
+ <a href="/foo/bar?page=2" class="next_page" rel="next">Next &#8594;</a></div>
115
+ HTML
116
+ expected.strip!.gsub!(/\s{2,}/, ' ')
117
+ expected_dom = HTML::Document.new(expected).root
118
+
119
+ html_document.root.should == expected_dom
120
+ end
121
+
122
+ it "should output escaped URLs" do
123
+ paginate({:page => 1, :per_page => 1, :total_entries => 2},
124
+ :page_links => false, :params => { :tag => '<br>' })
125
+
126
+ assert_select 'a[href]', 1 do |links|
127
+ query = links.first['href'].split('?', 2)[1]
128
+ query.split('&amp;').sort.should == %w(page=2 tag=%3Cbr%3E)
129
+ end
130
+ end
131
+
132
+ ## advanced options for pagination ##
133
+
134
+ it "should be able to render without container" do
135
+ paginate({}, :container => false)
136
+ assert_select 'div.pagination', 0, 'main DIV present when it shouldn\'t'
137
+ assert_select 'a[href]', 3
138
+ end
139
+
140
+ it "should be able to render without page links" do
141
+ paginate({ :page => 2 }, :page_links => false) do
142
+ assert_select 'a[href]', 2 do |elements|
143
+ validate_page_numbers [1,3], elements
144
+ end
145
+ end
146
+ end
147
+
148
+ it "should have magic HTML ID for the container" do
149
+ paginate do |div|
150
+ div.first['id'].should be_nil
151
+ end
152
+
153
+ # magic ID
154
+ paginate({}, :id => true) do |div|
155
+ div.first['id'].should == 'fixnums_pagination'
156
+ end
157
+
158
+ # explicit ID
159
+ paginate({}, :id => 'custom_id') do |div|
160
+ div.first['id'].should == 'custom_id'
161
+ end
162
+ end
163
+
164
+ ## other helpers ##
165
+
166
+ it "should render a paginated section" do
167
+ @template = <<-ERB
168
+ <% paginated_section collection, options do %>
169
+ <%= content_tag :div, '', :id => "developers" %>
170
+ <% end %>
171
+ ERB
172
+
173
+ paginate
174
+ assert_select 'div.pagination', 2
175
+ assert_select 'div.pagination + div#developers', 1
176
+ end
177
+
178
+ ## parameter handling in page links ##
179
+
180
+ it "should preserve parameters on GET" do
181
+ request.params :foo => { :bar => 'baz' }
182
+ paginate
183
+ assert_links_match /foo\[bar\]=baz/
184
+ end
185
+
186
+ it "should not preserve parameters on POST" do
187
+ request.post
188
+ request.params :foo => 'bar'
189
+ paginate
190
+ assert_no_links_match /foo=bar/
191
+ end
192
+
193
+ it "should add additional parameters to links" do
194
+ paginate({}, :params => { :foo => 'bar' })
195
+ assert_links_match /foo=bar/
196
+ end
197
+
198
+ it "should add anchor parameter" do
199
+ paginate({}, :params => { :anchor => 'anchor' })
200
+ assert_links_match /#anchor$/
201
+ end
202
+
203
+ it "should remove arbitrary parameters" do
204
+ request.params :foo => 'bar'
205
+ paginate({}, :params => { :foo => nil })
206
+ assert_no_links_match /foo=bar/
207
+ end
208
+
209
+ it "should override default route parameters" do
210
+ paginate({}, :params => { :controller => 'baz', :action => 'list' })
211
+ assert_links_match %r{\Wbaz/list\W}
212
+ end
213
+
214
+ it "should paginate with custom page parameter" do
215
+ paginate({ :page => 2 }, :param_name => :developers_page) do
216
+ assert_select 'a[href]', 4 do |elements|
217
+ validate_page_numbers [1,1,3,3], elements, :developers_page
218
+ end
219
+ end
220
+ end
221
+
222
+ it "should paginate with complex custom page parameter" do
223
+ request.params :developers => { :page => 2 }
224
+
225
+ paginate({ :page => 2 }, :param_name => 'developers[page]') do
226
+ assert_select 'a[href]', 4 do |links|
227
+ assert_links_match /\?developers\[page\]=\d+$/, links
228
+ validate_page_numbers [1,1,3,3], links, 'developers[page]'
229
+ end
230
+ end
231
+ end
232
+
233
+ it "should paginate with custom route page parameter" do
234
+ request.symbolized_path_parameters.update :controller => 'dummy', :action => nil
235
+ paginate :per_page => 2 do
236
+ assert_select 'a[href]', 6 do |links|
237
+ assert_links_match %r{/page/(\d+)$}, links, [2, 3, 4, 5, 6, 2]
238
+ end
239
+ end
240
+ end
241
+
242
+ it "should paginate with custom route with dot separator page parameter" do
243
+ request.symbolized_path_parameters.update :controller => 'dummy', :action => 'dots'
244
+ paginate :per_page => 2 do
245
+ assert_select 'a[href]', 6 do |links|
246
+ assert_links_match %r{/page\.(\d+)$}, links, [2, 3, 4, 5, 6, 2]
247
+ end
248
+ end
249
+ end
250
+
251
+ it "should paginate with custom route and first page number implicit" do
252
+ request.symbolized_path_parameters.update :controller => 'ibocorp', :action => nil
253
+ paginate :page => 2, :per_page => 2 do
254
+ assert_select 'a[href]', 7 do |links|
255
+ assert_links_match %r{/ibocorp(?:/(\d+))?$}, links, [nil, nil, 3, 4, 5, 6, 3]
256
+ end
257
+ end
258
+ end
259
+
260
+ ## internal hardcore stuff ##
261
+
262
+ it "should be able to guess the collection name" do
263
+ collection = mock
264
+ collection.expects(:total_pages).returns(1)
265
+
266
+ @template = '<%= will_paginate options %>'
267
+ controller.controller_name = 'developers'
268
+ assigns['developers'] = collection
269
+
270
+ paginate(nil)
271
+ end
272
+
273
+ it "should fail if the inferred collection is nil" do
274
+ @template = '<%= will_paginate options %>'
275
+ controller.controller_name = 'developers'
276
+
277
+ lambda {
278
+ paginate(nil)
279
+ }.should raise_error(ActionView::TemplateError, /@developers/)
280
+ end
281
+ end
282
+
283
+ class AdditionalLinkAttributesRenderer < WillPaginate::ViewHelpers::LinkRenderer
284
+ def initialize(link_attributes = nil)
285
+ super()
286
+ @additional_link_attributes = link_attributes || { :default => 'true' }
287
+ end
288
+
289
+ def link(text, target, attributes = {})
290
+ super(text, target, attributes.merge(@additional_link_attributes))
291
+ end
292
+ end
293
+
294
+ class DummyController
295
+ attr_reader :request
296
+ attr_accessor :controller_name
297
+
298
+ def initialize
299
+ @request = DummyRequest.new
300
+ @url = ActionController::UrlRewriter.new(@request, @request.params)
301
+ end
302
+
303
+ def params
304
+ @request.params
305
+ end
306
+
307
+ def url_for(params)
308
+ @url.rewrite(params)
309
+ end
310
+ end
311
+
312
+ class DummyRequest
313
+ attr_accessor :symbolized_path_parameters
314
+
315
+ def initialize
316
+ @get = true
317
+ @params = {}
318
+ @symbolized_path_parameters = { :controller => 'foo', :action => 'bar' }
319
+ end
320
+
321
+ def get?
322
+ @get
323
+ end
324
+
325
+ def post
326
+ @get = false
327
+ end
328
+
329
+ def relative_url_root
330
+ ''
331
+ end
332
+
333
+ def params(more = nil)
334
+ @params.update(more) if more
335
+ @params
336
+ end
337
+
338
+ def host_with_port
339
+ 'example.com'
340
+ end
341
+
342
+ def protocol
343
+ 'http:'
344
+ end
345
+ end