lib/will_paginate/collection.rb in will_paginate-2.1.0 vs lib/will_paginate/collection.rb in will_paginate-2.2.0
- old
+ new
@@ -1,42 +1,57 @@
-require 'will_paginate'
-
module WillPaginate
- # = OMG, invalid page number!
+ # = Invalid page number error
# This is an ArgumentError raised in case a page was requested that is either
# zero or negative number. You should decide how do deal with such errors in
# the controller.
#
+ # If you're using Rails 2, then this error will automatically get handled like
+ # 404 Not Found. The hook is in "will_paginate.rb":
+ #
+ # ActionController::Base.rescue_responses['WillPaginate::InvalidPage'] = :not_found
+ #
+ # If you don't like this, use your preffered method of rescuing exceptions in
+ # public from your controllers to handle this differently. The +rescue_from+
+ # method is a nice addition to Rails 2.
+ #
# This error is *not* raised when a page further than the last page is
# requested. Use <tt>WillPaginate::Collection#out_of_bounds?</tt> method to
# check for those cases and manually deal with them as you see fit.
class InvalidPage < ArgumentError
def initialize(page, page_num)
super "#{page.inspect} given as value, which translates to '#{page_num}' as page number"
end
end
- # Arrays returned from paginating finds are, in fact, instances of this.
- # You may think of WillPaginate::Collection as an ordinary array with some
- # extra properties. Those properties are used by view helpers to generate
+ # = The key to pagination
+ # Arrays returned from paginating finds are, in fact, instances of this little
+ # class. You may think of WillPaginate::Collection as an ordinary array with
+ # some extra properties. Those properties are used by view helpers to generate
# correct page links.
#
# WillPaginate::Collection also assists in rolling out your own pagination
# solutions: see +create+.
+ #
+ # If you are writing a library that provides a collection which you would like
+ # to conform to this API, you don't have to copy these methods over; simply
+ # make your plugin/gem dependant on the "will_paginate" gem:
#
+ # gem 'will_paginate'
+ # require 'will_paginate/collection'
+ #
+ # # now use WillPaginate::Collection directly or subclass it
class Collection < Array
- attr_reader :current_page, :per_page, :total_entries
+ attr_reader :current_page, :per_page, :total_entries, :total_pages
- # Arguments to this constructor are the current page number, per-page limit
+ # Arguments to the constructor are the current page number, per-page limit
# and the total number of entries. The last argument is optional because it
# is best to do lazy counting; in other words, count *conditionally* after
# populating the collection using the +replace+ method.
- #
def initialize(page, per_page, total = nil)
@current_page = page.to_i
raise InvalidPage.new(page, @current_page) if @current_page < 1
- @per_page = per_page.to_i
+ @per_page = per_page.to_i
raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1
self.total_entries = total if total
end
@@ -63,33 +78,29 @@
# pager.replace self[pager.offset, pager.per_page].to_a
# end
# end
# end
#
+ # The Array#paginate API has since then changed, but this still serves as a
+ # fine example of WillPaginate::Collection usage.
def self.create(page, per_page, total = nil, &block)
pager = new(page, per_page, total)
yield pager
pager
end
- # The total number of pages.
- def page_count
- @total_pages
- end
-
# Helper method that is true when someone tries to fetch a page with a
# larger number than the last page. Can be used in combination with flashes
# and redirecting.
def out_of_bounds?
- current_page > page_count
+ current_page > total_pages
end
# Current offset of the paginated collection. If we're on the first page,
# it is always 0. If we're on the 2nd page and there are 30 entries per page,
# the offset is 30. This property is useful if you want to render ordinals
# besides your records: simply start with offset + 1.
- #
def offset
(current_page - 1) * per_page
end
# current_page - 1 or nil if there is no previous page
@@ -97,11 +108,11 @@
current_page > 1 ? (current_page - 1) : nil
end
# current_page + 1 or nil if there is no next page
def next_page
- current_page < page_count ? (current_page + 1) : nil
+ current_page < total_pages ? (current_page + 1) : nil
end
def total_entries=(number)
@total_entries = number.to_i
@total_pages = (@total_entries / per_page.to_f).ceil
@@ -118,15 +129,17 @@
#
# However, after using +replace+ you should always test the value of
# +total_entries+ and set it to a proper value if it's +nil+. See the example
# in +create+.
def replace(array)
- returning super do
- # The collection is shorter then page limit? Rejoice, because
- # then we know that we are on the last page!
- if total_entries.nil? and length > 0 and length < per_page
- self.total_entries = offset + length
- end
+ result = super
+
+ # The collection is shorter then page limit? Rejoice, because
+ # then we know that we are on the last page!
+ if total_entries.nil? and length < per_page and (current_page == 1 or length > 0)
+ self.total_entries = offset + length
end
+
+ result
end
end
end