kamal-will_paginate 2.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGELOG.rdoc +110 -0
  2. data/LICENSE +18 -0
  3. data/README.rdoc +107 -0
  4. data/Rakefile +62 -0
  5. data/examples/apple-circle.gif +0 -0
  6. data/examples/index.haml +69 -0
  7. data/examples/index.html +92 -0
  8. data/examples/pagination.css +90 -0
  9. data/examples/pagination.sass +91 -0
  10. data/init.rb +1 -0
  11. data/lib/will_paginate.rb +78 -0
  12. data/lib/will_paginate/array.rb +16 -0
  13. data/lib/will_paginate/collection.rb +146 -0
  14. data/lib/will_paginate/core_ext.rb +32 -0
  15. data/lib/will_paginate/finder.rb +264 -0
  16. data/lib/will_paginate/named_scope.rb +170 -0
  17. data/lib/will_paginate/named_scope_patch.rb +37 -0
  18. data/lib/will_paginate/version.rb +9 -0
  19. data/lib/will_paginate/view_helpers.rb +402 -0
  20. data/test/boot.rb +21 -0
  21. data/test/collection_test.rb +143 -0
  22. data/test/console +8 -0
  23. data/test/database.yml +22 -0
  24. data/test/finder_test.rb +476 -0
  25. data/test/fixtures/admin.rb +3 -0
  26. data/test/fixtures/developer.rb +14 -0
  27. data/test/fixtures/developers_projects.yml +13 -0
  28. data/test/fixtures/project.rb +15 -0
  29. data/test/fixtures/projects.yml +6 -0
  30. data/test/fixtures/replies.yml +29 -0
  31. data/test/fixtures/reply.rb +7 -0
  32. data/test/fixtures/schema.rb +38 -0
  33. data/test/fixtures/topic.rb +10 -0
  34. data/test/fixtures/topics.yml +30 -0
  35. data/test/fixtures/user.rb +2 -0
  36. data/test/fixtures/users.yml +35 -0
  37. data/test/helper.rb +40 -0
  38. data/test/lib/activerecord_test_case.rb +43 -0
  39. data/test/lib/activerecord_test_connector.rb +75 -0
  40. data/test/lib/load_fixtures.rb +11 -0
  41. data/test/lib/view_test_process.rb +178 -0
  42. data/test/tasks.rake +59 -0
  43. data/test/view_test.rb +365 -0
  44. metadata +132 -0
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
3
+ libs = []
4
+
5
+ libs << 'irb/completion'
6
+ libs << File.join('lib', 'load_fixtures')
7
+
8
+ exec "#{irb} -Ilib:test#{libs.map{ |l| " -r #{l}" }.join} --simple-prompt"
@@ -0,0 +1,22 @@
1
+ sqlite3:
2
+ database: ":memory:"
3
+ adapter: sqlite3
4
+ timeout: 500
5
+
6
+ sqlite2:
7
+ database: ":memory:"
8
+ adapter: sqlite2
9
+
10
+ mysql:
11
+ adapter: mysql
12
+ username: root
13
+ password:
14
+ encoding: utf8
15
+ database: will_paginate_unittest
16
+
17
+ postgres:
18
+ adapter: postgresql
19
+ username: mislav
20
+ password:
21
+ database: will_paginate_unittest
22
+ min_messages: warning
@@ -0,0 +1,476 @@
1
+ require 'helper'
2
+ require 'lib/activerecord_test_case'
3
+
4
+ require 'will_paginate'
5
+ WillPaginate.enable_activerecord
6
+ WillPaginate.enable_named_scope
7
+
8
+ class FinderTest < ActiveRecordTestCase
9
+ fixtures :topics, :replies, :users, :projects, :developers_projects
10
+
11
+ def test_new_methods_presence
12
+ assert_respond_to_all Topic, %w(per_page paginate paginate_by_sql)
13
+ end
14
+
15
+ def test_simple_paginate
16
+ assert_queries(1) do
17
+ entries = Topic.paginate :page => nil
18
+ assert_equal 1, entries.current_page
19
+ assert_equal 1, entries.total_pages
20
+ assert_equal 4, entries.size
21
+ end
22
+
23
+ assert_queries(2) do
24
+ entries = Topic.paginate :page => 2
25
+ assert_equal 1, entries.total_pages
26
+ assert entries.empty?
27
+ end
28
+ end
29
+
30
+ def test_parameter_api
31
+ # :page parameter in options is required!
32
+ assert_raise(ArgumentError){ Topic.paginate }
33
+ assert_raise(ArgumentError){ Topic.paginate({}) }
34
+
35
+ # explicit :all should not break anything
36
+ assert_equal Topic.paginate(:page => nil), Topic.paginate(:all, :page => 1)
37
+
38
+ # :count could be nil and we should still not cry
39
+ assert_nothing_raised { Topic.paginate :page => 1, :count => nil }
40
+ end
41
+
42
+ def test_paginate_with_per_page
43
+ entries = Topic.paginate :page => 1, :per_page => 1
44
+ assert_equal 1, entries.size
45
+ assert_equal 4, entries.total_pages
46
+
47
+ # Developer class has explicit per_page at 10
48
+ entries = Developer.paginate :page => 1
49
+ assert_equal 10, entries.size
50
+ assert_equal 2, entries.total_pages
51
+
52
+ entries = Developer.paginate :page => 1, :per_page => 5
53
+ assert_equal 11, entries.total_entries
54
+ assert_equal 5, entries.size
55
+ assert_equal 3, entries.total_pages
56
+ end
57
+
58
+ def test_paginate_with_order
59
+ entries = Topic.paginate :page => 1, :order => 'created_at desc'
60
+ expected = [topics(:futurama), topics(:harvey_birdman), topics(:rails), topics(:ar)].reverse
61
+ assert_equal expected, entries.to_a
62
+ assert_equal 1, entries.total_pages
63
+ end
64
+
65
+ def test_paginate_with_conditions
66
+ entries = Topic.paginate :page => 1, :conditions => ["created_at > ?", 30.minutes.ago]
67
+ expected = [topics(:rails), topics(:ar)]
68
+ assert_equal expected, entries.to_a
69
+ assert_equal 1, entries.total_pages
70
+ end
71
+
72
+ def test_paginate_with_include_and_conditions
73
+ entries = Topic.paginate \
74
+ :page => 1,
75
+ :include => :replies,
76
+ :conditions => "replies.content LIKE 'Bird%' ",
77
+ :per_page => 10
78
+
79
+ expected = Topic.find :all,
80
+ :include => 'replies',
81
+ :conditions => "replies.content LIKE 'Bird%' ",
82
+ :limit => 10
83
+
84
+ assert_equal expected, entries.to_a
85
+ assert_equal 1, entries.total_entries
86
+ end
87
+
88
+ def test_paginate_with_include_and_order
89
+ entries = nil
90
+ assert_queries(2) do
91
+ entries = Topic.paginate \
92
+ :page => 1,
93
+ :include => :replies,
94
+ :order => 'replies.created_at asc, topics.created_at asc',
95
+ :per_page => 10
96
+ end
97
+
98
+ expected = Topic.find :all,
99
+ :include => 'replies',
100
+ :order => 'replies.created_at asc, topics.created_at asc',
101
+ :limit => 10
102
+
103
+ assert_equal expected, entries.to_a
104
+ assert_equal 4, entries.total_entries
105
+ end
106
+
107
+ def test_paginate_associations_with_include
108
+ entries, project = nil, projects(:active_record)
109
+
110
+ assert_nothing_raised "THIS IS A BUG in Rails 1.2.3 that was fixed in [7326]. " +
111
+ "Please upgrade to a newer version of Rails." do
112
+ entries = project.topics.paginate \
113
+ :page => 1,
114
+ :include => :replies,
115
+ :conditions => "replies.content LIKE 'Nice%' ",
116
+ :per_page => 10
117
+ end
118
+
119
+ expected = Topic.find :all,
120
+ :include => 'replies',
121
+ :conditions => "project_id = #{project.id} AND replies.content LIKE 'Nice%' ",
122
+ :limit => 10
123
+
124
+ assert_equal expected, entries.to_a
125
+ end
126
+
127
+ def test_paginate_associations
128
+ dhh = users :david
129
+ expected_name_ordered = [projects(:action_controller), projects(:active_record)]
130
+ expected_id_ordered = [projects(:active_record), projects(:action_controller)]
131
+
132
+ assert_queries(2) do
133
+ # with association-specified order
134
+ entries = dhh.projects.paginate(:page => 1)
135
+ assert_equal expected_name_ordered, entries
136
+ assert_equal 2, entries.total_entries
137
+ end
138
+
139
+ # with explicit order
140
+ entries = dhh.projects.paginate(:page => 1, :order => 'projects.id')
141
+ assert_equal expected_id_ordered, entries
142
+ assert_equal 2, entries.total_entries
143
+
144
+ assert_nothing_raised { dhh.projects.find(:all, :order => 'projects.id', :limit => 4) }
145
+ entries = dhh.projects.paginate(:page => 1, :order => 'projects.id', :per_page => 4)
146
+ assert_equal expected_id_ordered, entries
147
+
148
+ # has_many with implicit order
149
+ topic = Topic.find(1)
150
+ expected = [replies(:spam), replies(:witty_retort)]
151
+ assert_equal expected.map(&:id).sort, topic.replies.paginate(:page => 1).map(&:id).sort
152
+ assert_equal expected.reverse, topic.replies.paginate(:page => 1, :order => 'replies.id ASC')
153
+ end
154
+
155
+ def test_paginate_association_extension
156
+ project = Project.find(:first)
157
+
158
+ assert_queries(2) do
159
+ entries = project.replies.paginate_recent :page => 1
160
+ assert_equal [replies(:brave)], entries
161
+ end
162
+ end
163
+
164
+ def test_paginate_with_joins
165
+ entries = nil
166
+
167
+ assert_queries(1) do
168
+ entries = Developer.paginate :page => 1,
169
+ :joins => 'LEFT JOIN developers_projects ON users.id = developers_projects.developer_id',
170
+ :conditions => 'project_id = 1'
171
+ assert_equal 2, entries.size
172
+ developer_names = entries.map &:name
173
+ assert developer_names.include?('David')
174
+ assert developer_names.include?('Jamis')
175
+ end
176
+
177
+ assert_queries(1) do
178
+ expected = entries.to_a
179
+ entries = Developer.paginate :page => 1,
180
+ :joins => 'LEFT JOIN developers_projects ON users.id = developers_projects.developer_id',
181
+ :conditions => 'project_id = 1', :count => { :select => "users.id" }
182
+ assert_equal expected, entries.to_a
183
+ assert_equal 2, entries.total_entries
184
+ end
185
+ end
186
+
187
+ def test_paginate_with_group
188
+ entries = nil
189
+ assert_queries(1) do
190
+ entries = Developer.paginate :page => 1, :per_page => 10,
191
+ :group => 'salary', :select => 'salary', :order => 'salary'
192
+ end
193
+
194
+ expected = [ users(:david), users(:jamis), users(:dev_10), users(:poor_jamis) ].map(&:salary).sort
195
+ assert_equal expected, entries.map(&:salary)
196
+ end
197
+
198
+ def test_paginate_with_dynamic_finder
199
+ expected = [replies(:witty_retort), replies(:spam)]
200
+ assert_equal expected, Reply.paginate_by_topic_id(1, :page => 1)
201
+
202
+ entries = Developer.paginate :conditions => { :salary => 100000 }, :page => 1, :per_page => 5
203
+ assert_equal 8, entries.total_entries
204
+ assert_equal entries, Developer.paginate_by_salary(100000, :page => 1, :per_page => 5)
205
+
206
+ # dynamic finder + conditions
207
+ entries = Developer.paginate_by_salary(100000, :page => 1,
208
+ :conditions => ['id > ?', 6])
209
+ assert_equal 4, entries.total_entries
210
+ assert_equal (7..10).to_a, entries.map(&:id)
211
+
212
+ assert_raises NoMethodError do
213
+ Developer.paginate_by_inexistent_attribute 100000, :page => 1
214
+ end
215
+ end
216
+
217
+ def test_scoped_paginate
218
+ entries = Developer.with_poor_ones { Developer.paginate :page => 1 }
219
+
220
+ assert_equal 2, entries.size
221
+ assert_equal 2, entries.total_entries
222
+ end
223
+
224
+ ## named_scope ##
225
+
226
+ def test_paginate_in_named_scope
227
+ entries = Developer.poor.paginate :page => 1, :per_page => 1
228
+
229
+ assert_equal 1, entries.size
230
+ assert_equal 2, entries.total_entries
231
+ end
232
+
233
+ def test_paginate_in_named_scope_on_habtm_association
234
+ project = projects(:active_record)
235
+ assert_queries(2) do
236
+ entries = project.developers.poor.paginate :page => 1, :per_page => 1
237
+
238
+ assert_equal 1, entries.size, 'one developer should be found'
239
+ assert_equal 1, entries.total_entries, 'only one developer should be found'
240
+ end
241
+ end
242
+
243
+ def test_paginate_in_named_scope_on_hmt_association
244
+ project = projects(:active_record)
245
+ expected = [replies(:brave)]
246
+
247
+ assert_queries(2) do
248
+ entries = project.replies.recent.paginate :page => 1, :per_page => 1
249
+ assert_equal expected, entries
250
+ assert_equal 1, entries.total_entries, 'only one reply should be found'
251
+ end
252
+ end
253
+
254
+ def test_paginate_in_named_scope_on_has_many_association
255
+ project = projects(:active_record)
256
+ expected = [topics(:ar)]
257
+
258
+ assert_queries(2) do
259
+ entries = project.topics.mentions_activerecord.paginate :page => 1, :per_page => 1
260
+ assert_equal expected, entries
261
+ assert_equal 1, entries.total_entries, 'only one topic should be found'
262
+ end
263
+ end
264
+
265
+ def test_named_scope_with_include
266
+ project = projects(:active_record)
267
+ entries = project.topics.with_replies_starting_with('AR ').paginate(:page => 1, :per_page => 1)
268
+ assert_equal 1, entries.size
269
+ end
270
+
271
+ ## misc ##
272
+
273
+ def test_count_and_total_entries_options_are_mutually_exclusive
274
+ e = assert_raise ArgumentError do
275
+ Developer.paginate :page => 1, :count => {}, :total_entries => 1
276
+ end
277
+ assert_match /exclusive/, e.to_s
278
+ end
279
+
280
+ def test_readonly
281
+ assert_nothing_raised { Developer.paginate :readonly => true, :page => 1 }
282
+ end
283
+
284
+ # this functionality is temporarily removed
285
+ def xtest_pagination_defines_method
286
+ pager = "paginate_by_created_at"
287
+ assert !User.methods.include?(pager), "User methods should not include `#{pager}` method"
288
+ # paginate!
289
+ assert 0, User.send(pager, nil, :page => 1).total_entries
290
+ # the paging finder should now be defined
291
+ assert User.methods.include?(pager), "`#{pager}` method should be defined on User"
292
+ end
293
+
294
+ # Is this Rails 2.0? Find out by testing find_all which was removed in [6998]
295
+ unless ActiveRecord::Base.respond_to? :find_all
296
+ def test_paginate_array_of_ids
297
+ # AR finders also accept arrays of IDs
298
+ # (this was broken in Rails before [6912])
299
+ assert_queries(1) do
300
+ entries = Developer.paginate((1..8).to_a, :per_page => 3, :page => 2, :order => 'id')
301
+ assert_equal (4..6).to_a, entries.map(&:id)
302
+ assert_equal 8, entries.total_entries
303
+ end
304
+ end
305
+ end
306
+
307
+ uses_mocha 'internals' do
308
+ def test_implicit_all_with_dynamic_finders
309
+ Topic.expects(:find_all_by_foo).returns([])
310
+ Topic.expects(:count).returns(0)
311
+ Topic.paginate_by_foo :page => 2
312
+ end
313
+
314
+ def test_guessing_the_total_count
315
+ Topic.expects(:find).returns(Array.new(2))
316
+ Topic.expects(:count).never
317
+
318
+ entries = Topic.paginate :page => 2, :per_page => 4
319
+ assert_equal 6, entries.total_entries
320
+ end
321
+
322
+ def test_guessing_that_there_are_no_records
323
+ Topic.expects(:find).returns([])
324
+ Topic.expects(:count).never
325
+
326
+ entries = Topic.paginate :page => 1, :per_page => 4
327
+ assert_equal 0, entries.total_entries
328
+ end
329
+
330
+ def test_extra_parameters_stay_untouched
331
+ Topic.expects(:find).with(:all, {:foo => 'bar', :limit => 4, :offset => 0 }).returns(Array.new(5))
332
+ Topic.expects(:count).with({:foo => 'bar'}).returns(1)
333
+
334
+ Topic.paginate :foo => 'bar', :page => 1, :per_page => 4
335
+ end
336
+
337
+ def test_count_skips_select
338
+ Developer.stubs(:find).returns([])
339
+ Developer.expects(:count).with({}).returns(0)
340
+ Developer.paginate :select => 'salary', :page => 2
341
+ end
342
+
343
+ def test_count_select_when_distinct
344
+ Developer.stubs(:find).returns([])
345
+ Developer.expects(:count).with(:select => 'DISTINCT salary').returns(0)
346
+ Developer.paginate :select => 'DISTINCT salary', :page => 2
347
+ end
348
+
349
+ def test_count_with_scoped_select_when_distinct
350
+ Developer.stubs(:find).returns([])
351
+ Developer.expects(:count).with(:select => 'DISTINCT users.id').returns(0)
352
+ Developer.distinct.paginate :page => 2
353
+ end
354
+
355
+ def test_should_use_scoped_finders_if_present
356
+ # scope-out compatibility
357
+ Topic.expects(:find_best).returns(Array.new(5))
358
+ Topic.expects(:with_best).returns(1)
359
+
360
+ Topic.paginate_best :page => 1, :per_page => 4
361
+ end
362
+
363
+ def test_paginate_by_sql
364
+ assert_respond_to Developer, :paginate_by_sql
365
+ Developer.expects(:find_by_sql).with(regexp_matches(/sql LIMIT 3(,| OFFSET) 3/)).returns([])
366
+ Developer.expects(:count_by_sql).with('SELECT COUNT(*) FROM (sql) AS count_table').returns(0)
367
+
368
+ entries = Developer.paginate_by_sql 'sql', :page => 2, :per_page => 3
369
+ end
370
+
371
+ def test_paginate_by_sql_respects_total_entries_setting
372
+ Developer.expects(:find_by_sql).returns([])
373
+ Developer.expects(:count_by_sql).never
374
+
375
+ entries = Developer.paginate_by_sql 'sql', :page => 1, :total_entries => 999
376
+ assert_equal 999, entries.total_entries
377
+ end
378
+
379
+ def test_paginate_by_sql_strips_order_by_when_counting
380
+ Developer.expects(:find_by_sql).returns([])
381
+ Developer.expects(:count_by_sql).with("SELECT COUNT(*) FROM (sql\n ) AS count_table").returns(0)
382
+
383
+ Developer.paginate_by_sql "sql\n ORDER\nby foo, bar, `baz` ASC", :page => 2
384
+ end
385
+
386
+ # TODO: counts are still wrong
387
+ def test_ability_to_use_with_custom_finders
388
+ # acts_as_taggable defines find_tagged_with(tag, options)
389
+ Topic.expects(:find_tagged_with).with('will_paginate', :offset => 5, :limit => 5).returns([])
390
+ Topic.expects(:count).with({}).returns(0)
391
+
392
+ Topic.paginate_tagged_with 'will_paginate', :page => 2, :per_page => 5
393
+ end
394
+
395
+ def test_array_argument_doesnt_eliminate_count
396
+ ids = (1..8).to_a
397
+ Developer.expects(:find_all_by_id).returns([])
398
+ Developer.expects(:count).returns(0)
399
+
400
+ Developer.paginate_by_id(ids, :per_page => 3, :page => 2, :order => 'id')
401
+ end
402
+
403
+ def test_paginating_finder_doesnt_mangle_options
404
+ Developer.expects(:find).returns([])
405
+ options = { :page => 1, :per_page => 2, :foo => 'bar' }
406
+ options_before = options.dup
407
+
408
+ Developer.paginate(options)
409
+ assert_equal options_before, options
410
+ end
411
+
412
+ def test_paginate_by_sql_doesnt_change_original_query
413
+ query = 'SQL QUERY'
414
+ original_query = query.dup
415
+ Developer.expects(:find_by_sql).returns([])
416
+
417
+ Developer.paginate_by_sql query, :page => 1
418
+ assert_equal original_query, query
419
+ end
420
+
421
+ def test_paginated_each
422
+ collection = stub('collection', :size => 5, :empty? => false, :per_page => 5)
423
+ collection.expects(:each).times(2).returns(collection)
424
+ last_collection = stub('collection', :size => 4, :empty? => false, :per_page => 5)
425
+ last_collection.expects(:each).returns(last_collection)
426
+
427
+ params = { :order => 'id', :total_entries => 0 }
428
+
429
+ Developer.expects(:paginate).with(params.merge(:page => 2)).returns(collection)
430
+ Developer.expects(:paginate).with(params.merge(:page => 3)).returns(collection)
431
+ Developer.expects(:paginate).with(params.merge(:page => 4)).returns(last_collection)
432
+
433
+ assert_equal 14, Developer.paginated_each(:page => '2') { }
434
+ end
435
+
436
+ def test_paginated_each_with_named_scope
437
+ assert_equal 2, Developer.poor.paginated_each(:per_page => 1) {
438
+ assert_equal 11, Developer.count
439
+ }
440
+ end
441
+
442
+ # detect ActiveRecord 2.1
443
+ if ActiveRecord::Base.private_methods.include?('references_eager_loaded_tables?')
444
+ def test_removes_irrelevant_includes_in_count
445
+ Developer.expects(:find).returns([1])
446
+ Developer.expects(:count).with({}).returns(0)
447
+
448
+ Developer.paginate :page => 1, :per_page => 1, :include => :projects
449
+ end
450
+
451
+ def test_doesnt_remove_referenced_includes_in_count
452
+ Developer.expects(:find).returns([1])
453
+ Developer.expects(:count).with({ :include => :projects, :conditions => 'projects.id > 2' }).returns(0)
454
+
455
+ Developer.paginate :page => 1, :per_page => 1,
456
+ :include => :projects, :conditions => 'projects.id > 2'
457
+ end
458
+ end
459
+
460
+ def test_paginate_from
461
+ result = Developer.paginate(:from => 'users', :page => 1, :per_page => 1)
462
+ assert_equal 1, result.size
463
+ end
464
+
465
+ def test_hmt_with_include
466
+ # ticket #220
467
+ reply = projects(:active_record).replies.find(:first, :order => 'replies.id')
468
+ assert_equal replies(:decisive), reply
469
+
470
+ # ticket #223
471
+ Project.find(1, :include => :replies)
472
+
473
+ # I cannot reproduce any of the failures from those reports :(
474
+ end
475
+ end
476
+ end