|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
1 |
module WillPaginate |
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
2 |
# = Invalid page number error |
|
138f0049
»
|
mislav |
2007-12-24 |
Will Paginate Christmas doc... |
3 |
# This is an ArgumentError raised in case a page was requested that is either |
| |
4 |
# zero or negative number. You should decide how do deal with such errors in |
| |
5 |
# the controller. |
| |
6 |
# |
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
7 |
# If you're using Rails 2, then this error will automatically get handled like |
| |
8 |
# 404 Not Found. The hook is in "will_paginate.rb": |
| |
9 |
# |
| |
10 |
# ActionController::Base.rescue_responses['WillPaginate::InvalidPage'] = :not_found |
| |
11 |
# |
| |
12 |
# If you don't like this, use your preffered method of rescuing exceptions in |
| |
13 |
# public from your controllers to handle this differently. The +rescue_from+ |
| |
14 |
# method is a nice addition to Rails 2. |
| |
15 |
# |
|
138f0049
»
|
mislav |
2007-12-24 |
Will Paginate Christmas doc... |
16 |
# This error is *not* raised when a page further than the last page is |
|
0e5528b0
»
|
mislav |
2007-12-24 |
Will Paginate now has the o... |
17 |
# requested. Use <tt>WillPaginate::Collection#out_of_bounds?</tt> method to |
| |
18 |
# check for those cases and manually deal with them as you see fit. |
|
1c6d4237
»
|
mislav |
2007-12-23 |
Will Paginate now frowns on... |
19 |
class InvalidPage < ArgumentError |
| |
20 |
def initialize(page, page_num) |
| |
21 |
super "#{page.inspect} given as value, which translates to '#{page_num}' as page number" |
| |
22 |
end |
| |
23 |
end |
| |
24 |
|
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
25 |
# = The key to pagination |
| |
26 |
# Arrays returned from paginating finds are, in fact, instances of this little |
| |
27 |
# class. You may think of WillPaginate::Collection as an ordinary array with |
| |
28 |
# some extra properties. Those properties are used by view helpers to generate |
|
8ee293e0
»
|
mislav |
2007-06-13 |
Bunch of nice stuff: bugfix... |
29 |
# correct page links. |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
30 |
# |
|
ba2d2cc0
»
|
mislav |
2007-10-07 |
Will Paingate dox spellchec... |
31 |
# WillPaginate::Collection also assists in rolling out your own pagination |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
32 |
# solutions: see +create+. |
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
33 |
# |
| |
34 |
# If you are writing a library that provides a collection which you would like |
| |
35 |
# to conform to this API, you don't have to copy these methods over; simply |
|
48d409a2
»
|
mislav |
2008-08-13 |
RDoc love (now live at http... |
36 |
# make your plugin/gem dependant on the "mislav-will_paginate" gem: |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
37 |
# |
|
48d409a2
»
|
mislav |
2008-08-13 |
RDoc love (now live at http... |
38 |
# gem 'mislav-will_paginate' |
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
39 |
# require 'will_paginate/collection' |
| |
40 |
# |
|
48d409a2
»
|
mislav |
2008-08-13 |
RDoc love (now live at http... |
41 |
# # WillPaginate::Collection is now available for use |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
42 |
class Collection < Array |
|
9158a472
»
|
mislav |
2008-04-03 |
Rename WillPaginate::Collec... |
43 |
attr_reader :current_page, :per_page, :total_entries, :total_pages |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
44 |
|
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
45 |
# Arguments to the constructor are the current page number, per-page limit |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
46 |
# and the total number of entries. The last argument is optional because it |
| |
47 |
# is best to do lazy counting; in other words, count *conditionally* after |
| |
48 |
# populating the collection using the +replace+ method. |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
49 |
def initialize(page, per_page, total = nil) |
| |
50 |
@current_page = page.to_i |
|
1c6d4237
»
|
mislav |
2007-12-23 |
Will Paginate now frowns on... |
51 |
raise InvalidPage.new(page, @current_page) if @current_page < 1 |
|
0fc17eb5
»
|
mislav |
2008-04-01 |
don't require 'will_paginat... |
52 |
@per_page = per_page.to_i |
|
1c6d4237
»
|
mislav |
2007-12-23 |
Will Paginate now frowns on... |
53 |
raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1 |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
54 |
|
| |
55 |
self.total_entries = total if total |
| |
56 |
end |
| |
57 |
|
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
58 |
# Just like +new+, but yields the object after instantiation and returns it |
| |
59 |
# afterwards. This is very useful for manual pagination: |
| |
60 |
# |
| |
61 |
# @entries = WillPaginate::Collection.create(1, 10) do |pager| |
| |
62 |
# result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset) |
| |
63 |
# # inject the result array into the paginated collection: |
| |
64 |
# pager.replace(result) |
| |
65 |
# |
| |
66 |
# unless pager.total_entries |
| |
67 |
# # the pager didn't manage to guess the total count, do it manually |
| |
68 |
# pager.total_entries = Post.count |
| |
69 |
# end |
| |
70 |
# end |
| |
71 |
# |
| |
72 |
# The possibilities with this are endless. For another example, here is how |
|
0e5528b0
»
|
mislav |
2007-12-24 |
Will Paginate now has the o... |
73 |
# WillPaginate used to define pagination for Array instances: |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
74 |
# |
| |
75 |
# Array.class_eval do |
| |
76 |
# def paginate(page = 1, per_page = 15) |
| |
77 |
# WillPaginate::Collection.create(page, per_page, size) do |pager| |
| |
78 |
# pager.replace self[pager.offset, pager.per_page].to_a |
| |
79 |
# end |
| |
80 |
# end |
| |
81 |
# end |
| |
82 |
# |
|
44fe4cc2
»
|
mislav |
2008-04-04 |
doc love all around |
83 |
# The Array#paginate API has since then changed, but this still serves as a |
| |
84 |
# fine example of WillPaginate::Collection usage. |
|
029964fe
»
|
Darrick Wiebe |
2009-02-09 |
Removed all unnecessary &bl... |
85 |
def self.create(page, per_page, total = nil) |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
86 |
pager = new(page, per_page, total) |
| |
87 |
yield pager |
| |
88 |
pager |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
89 |
end |
| |
90 |
|
|
1c6d4237
»
|
mislav |
2007-12-23 |
Will Paginate now frowns on... |
91 |
# Helper method that is true when someone tries to fetch a page with a |
| |
92 |
# larger number than the last page. Can be used in combination with flashes |
| |
93 |
# and redirecting. |
|
b44d79e0
»
|
mislav |
2007-10-06 |
Don't guess total count whe... |
94 |
def out_of_bounds? |
|
9158a472
»
|
mislav |
2008-04-03 |
Rename WillPaginate::Collec... |
95 |
current_page > total_pages |
|
b44d79e0
»
|
mislav |
2007-10-06 |
Don't guess total count whe... |
96 |
end |
| |
97 |
|
|
8ee293e0
»
|
mislav |
2007-06-13 |
Bunch of nice stuff: bugfix... |
98 |
# Current offset of the paginated collection. If we're on the first page, |
| |
99 |
# it is always 0. If we're on the 2nd page and there are 30 entries per page, |
| |
100 |
# the offset is 30. This property is useful if you want to render ordinals |
|
48d409a2
»
|
mislav |
2008-08-13 |
RDoc love (now live at http... |
101 |
# side by side with records in the view: simply start with offset + 1. |
|
97d63b11
»
|
mislav |
2007-06-06 |
first_index is renamed to "... |
102 |
def offset |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
103 |
(current_page - 1) * per_page |
| |
104 |
end |
|
97d63b11
»
|
mislav |
2007-06-06 |
first_index is renamed to "... |
105 |
|
|
8ee293e0
»
|
mislav |
2007-06-13 |
Bunch of nice stuff: bugfix... |
106 |
# current_page - 1 or nil if there is no previous page |
|
97d63b11
»
|
mislav |
2007-06-06 |
first_index is renamed to "... |
107 |
def previous_page |
| |
108 |
current_page > 1 ? (current_page - 1) : nil |
| |
109 |
end |
| |
110 |
|
|
8ee293e0
»
|
mislav |
2007-06-13 |
Bunch of nice stuff: bugfix... |
111 |
# current_page + 1 or nil if there is no next page |
|
97d63b11
»
|
mislav |
2007-06-06 |
first_index is renamed to "... |
112 |
def next_page |
|
9158a472
»
|
mislav |
2008-04-03 |
Rename WillPaginate::Collec... |
113 |
current_page < total_pages ? (current_page + 1) : nil |
|
97d63b11
»
|
mislav |
2007-06-06 |
first_index is renamed to "... |
114 |
end |
|
48d409a2
»
|
mislav |
2008-08-13 |
RDoc love (now live at http... |
115 |
|
| |
116 |
# sets the <tt>total_entries</tt> property and calculates <tt>total_pages</tt> |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
117 |
def total_entries=(number) |
| |
118 |
@total_entries = number.to_i |
| |
119 |
@total_pages = (@total_entries / per_page.to_f).ceil |
| |
120 |
end |
| |
121 |
|
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
122 |
# This is a magic wrapper for the original Array#replace method. It serves |
| |
123 |
# for populating the paginated collection after initialization. |
| |
124 |
# |
|
ba2d2cc0
»
|
mislav |
2007-10-07 |
Will Paingate dox spellchec... |
125 |
# Why magic? Because it tries to guess the total number of entries judging |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
126 |
# by the size of given array. If it is shorter than +per_page+ limit, then we |
| |
127 |
# know we're on the last page. This trick is very useful for avoiding |
|
ba2d2cc0
»
|
mislav |
2007-10-07 |
Will Paingate dox spellchec... |
128 |
# unnecessary hits to the database to do the counting after we fetched the |
|
d5dee204
»
|
mislav |
2007-10-07 |
Will Paginate: more dox for... |
129 |
# data for the current page. |
| |
130 |
# |
| |
131 |
# However, after using +replace+ you should always test the value of |
| |
132 |
# +total_entries+ and set it to a proper value if it's +nil+. See the example |
| |
133 |
# in +create+. |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
134 |
def replace(array) |
|
61c6ddeb
»
|
mislav |
2008-04-01 |
don't use `returning`. now ... |
135 |
result = super |
| |
136 |
|
| |
137 |
# The collection is shorter then page limit? Rejoice, because |
| |
138 |
# then we know that we are on the last page! |
|
b4c00a7a
»
|
mislav |
2008-04-02 |
Add paginated_each method f... |
139 |
if total_entries.nil? and length < per_page and (current_page == 1 or length > 0) |
|
61c6ddeb
»
|
mislav |
2008-04-01 |
don't use `returning`. now ... |
140 |
self.total_entries = offset + length |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
141 |
end |
|
61c6ddeb
»
|
mislav |
2008-04-01 |
don't use `returning`. now ... |
142 |
|
| |
143 |
result |
|
406c6117
»
|
mislav |
2007-09-26 |
Will Paginate lazy counting... |
144 |
end |
|
ac36b026
»
|
mislav |
2007-05-28 |
Slight finder rewrite (yeah... |
145 |
end |
| |
146 |
end |