Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 137 lines (123 sloc) 5.164 kb
05fc834 @mislav refactor page number checking, add offset validation
authored
1 require 'will_paginate/per_page'
89cf147 @mislav represent the concept of page number with the PageNumber class
authored
2 require 'will_paginate/page_number'
05fc834 @mislav refactor page number checking, add offset validation
authored
3
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
4 module WillPaginate
26e8736 @mislav fix `total_pages`, `out_of_bounds?` for empty collections
authored
5 # Any will_paginate-compatible collection should have these methods:
6 #
7 # current_page, per_page, offset, total_entries, total_pages
8 #
9 # It can also define some of these optional methods:
10 #
11 # out_of_bounds?, previous_page, next_page
12 #
13 # This module provides few of these methods.
14 module CollectionMethods
15 def total_pages
16 total_entries.zero? ? 1 : (total_entries / per_page.to_f).ceil
17 end
18
19 # current_page - 1 or nil if there is no previous page
20 def previous_page
21 current_page > 1 ? (current_page - 1) : nil
22 end
23
24 # current_page + 1 or nil if there is no next page
25 def next_page
26 current_page < total_pages ? (current_page + 1) : nil
27 end
28
29 # Helper method that is true when someone tries to fetch a page with a
30 # larger number than the last page. Can be used in combination with flashes
31 # and redirecting.
32 def out_of_bounds?
33 current_page > total_pages
34 end
35 end
36
44fe4cc @mislav doc love all around
authored
37 # = The key to pagination
38 # Arrays returned from paginating finds are, in fact, instances of this little
39 # class. You may think of WillPaginate::Collection as an ordinary array with
40 # some extra properties. Those properties are used by view helpers to generate
8ee293e Bunch of nice stuff: bugfix, docs, cleanup, test/console.
mislav authored
41 # correct page links.
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
42 #
ba2d2cc Will Paingate dox spellcheck ftw
mislav authored
43 # WillPaginate::Collection also assists in rolling out your own pagination
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
44 # solutions: see +create+.
44fe4cc @mislav doc love all around
authored
45 #
46 # If you are writing a library that provides a collection which you would like
47 # to conform to this API, you don't have to copy these methods over; simply
262419f @mislav remove reference to "mislav-will_paginate" gem from docs
authored
48 # make your plugin/gem dependant on this library and do:
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
49 #
44fe4cc @mislav doc love all around
authored
50 # require 'will_paginate/collection'
48d409a @mislav RDoc love (now live at http://mislav.caboo.se/static/will_paginate/doc/)
authored
51 # # WillPaginate::Collection is now available for use
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
52 class Collection < Array
26e8736 @mislav fix `total_pages`, `out_of_bounds?` for empty collections
authored
53 include CollectionMethods
54
55 attr_reader :current_page, :per_page, :total_entries
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
56
44fe4cc @mislav doc love all around
authored
57 # Arguments to the constructor are the current page number, per-page limit
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
58 # and the total number of entries. The last argument is optional because it
59 # is best to do lazy counting; in other words, count *conditionally* after
60 # populating the collection using the +replace+ method.
05fc834 @mislav refactor page number checking, add offset validation
authored
61 def initialize(page, per_page = WillPaginate.per_page, total = nil)
89cf147 @mislav represent the concept of page number with the PageNumber class
authored
62 @current_page = WillPaginate::PageNumber(page)
0fc17eb @mislav don't require 'will_paginate' in will_paginate/collection.rb, which e…
authored
63 @per_page = per_page.to_i
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
64 self.total_entries = total if total
65 end
66
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
67 # Just like +new+, but yields the object after instantiation and returns it
68 # afterwards. This is very useful for manual pagination:
69 #
70 # @entries = WillPaginate::Collection.create(1, 10) do |pager|
71 # result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
72 # # inject the result array into the paginated collection:
73 # pager.replace(result)
74 #
75 # unless pager.total_entries
76 # # the pager didn't manage to guess the total count, do it manually
77 # pager.total_entries = Post.count
78 # end
79 # end
80 #
81 # The possibilities with this are endless. For another example, here is how
0e5528b Will Paginate now has the option to disable rendering of page links (…
mislav authored
82 # WillPaginate used to define pagination for Array instances:
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
83 #
84 # Array.class_eval do
85 # def paginate(page = 1, per_page = 15)
86 # WillPaginate::Collection.create(page, per_page, size) do |pager|
87 # pager.replace self[pager.offset, pager.per_page].to_a
88 # end
89 # end
90 # end
91 #
44fe4cc @mislav doc love all around
authored
92 # The Array#paginate API has since then changed, but this still serves as a
93 # fine example of WillPaginate::Collection usage.
029964f Removed all unnecessary &block variables since they cause serious mem…
Darrick Wiebe authored
94 def self.create(page, per_page, total = nil)
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
95 pager = new(page, per_page, total)
96 yield pager
97 pager
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
98 end
99
8ee293e Bunch of nice stuff: bugfix, docs, cleanup, test/console.
mislav authored
100 # Current offset of the paginated collection. If we're on the first page,
101 # it is always 0. If we're on the 2nd page and there are 30 entries per page,
102 # the offset is 30. This property is useful if you want to render ordinals
48d409a @mislav RDoc love (now live at http://mislav.caboo.se/static/will_paginate/doc/)
authored
103 # side by side with records in the view: simply start with offset + 1.
97d63b1 first_index is renamed to "offset" again, makes more sense. Collectio…
mislav authored
104 def offset
26e8736 @mislav fix `total_pages`, `out_of_bounds?` for empty collections
authored
105 current_page.to_offset(per_page).to_i
97d63b1 first_index is renamed to "offset" again, makes more sense. Collectio…
mislav authored
106 end
107
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
108 def total_entries=(number)
109 @total_entries = number.to_i
110 end
111
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
112 # This is a magic wrapper for the original Array#replace method. It serves
113 # for populating the paginated collection after initialization.
114 #
ba2d2cc Will Paingate dox spellcheck ftw
mislav authored
115 # Why magic? Because it tries to guess the total number of entries judging
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
116 # by the size of given array. If it is shorter than +per_page+ limit, then we
117 # know we're on the last page. This trick is very useful for avoiding
ba2d2cc Will Paingate dox spellcheck ftw
mislav authored
118 # unnecessary hits to the database to do the counting after we fetched the
d5dee20 Will Paginate: more dox for WP::Collection, people seem to use it a lot
mislav authored
119 # data for the current page.
120 #
121 # However, after using +replace+ you should always test the value of
122 # +total_entries+ and set it to a proper value if it's +nil+. See the example
123 # in +create+.
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
124 def replace(array)
61c6dde @mislav don't use `returning`. now Collection is independent from ActiveSupport
authored
125 result = super
126
127 # The collection is shorter then page limit? Rejoice, because
128 # then we know that we are on the last page!
b4c00a7 @mislav Add paginated_each method for faking cursors. [Rick Olson]
authored
129 if total_entries.nil? and length < per_page and (current_page == 1 or length > 0)
61c6dde @mislav don't use `returning`. now Collection is independent from ActiveSupport
authored
130 self.total_entries = offset + length
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
131 end
61c6dde @mislav don't use `returning`. now Collection is independent from ActiveSupport
authored
132
133 result
406c611 Will Paginate lazy counting! Counting is done *after* the SELECT, but…
mislav authored
134 end
ac36b02 Slight finder rewrite (yeah, again ^^). PaginatedCollection is now Co…
mislav authored
135 end
136 end
Something went wrong with that request. Please try again.