Class: WillPaginate::Collection
- Defined in:
- lib/will_mostly_paginate/collection.rb
Overview
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 this library and do:
require 'will_paginate/collection'
# WillPaginate::Collection is now available for use
Instance Attribute Summary collapse
-
#current_page ⇒ Object
readonly
Returns the value of attribute current_page.
-
#next_exists ⇒ Object
Returns the value of attribute next_exists.
-
#page_all ⇒ Object
readonly
Returns the value of attribute page_all.
-
#per_page ⇒ Object
readonly
Returns the value of attribute per_page.
-
#total_entries ⇒ Object
Returns the value of attribute total_entries.
-
#total_pages ⇒ Object
readonly
Returns the value of attribute total_pages.
Class Method Summary collapse
-
.create(page, per_page, total = nil, page_all = true) {|pager| ... } ⇒ Object
Just like
new
, but yields the object after instantiation and returns it afterwards.
Instance Method Summary collapse
-
#initialize(page, per_page, total = nil, page_all = true) ⇒ Collection
constructor
Arguments to the constructor are the current page number, per-page limit the total number of entries, and whether or not to enumerate through all pages.
-
#next_page ⇒ Object
current_page + 1 or nil if there is no next page.
-
#offset ⇒ Object
Current offset of the paginated collection.
-
#out_of_bounds? ⇒ Boolean
Helper method that is true when someone tries to fetch a page with a larger number than the last page.
-
#previous_page ⇒ Object
current_page - 1 or nil if there is no previous page.
-
#replace(array) ⇒ Object
This is a magic wrapper for the original Array#replace method.
Methods inherited from Array
Constructor Details
#initialize(page, per_page, total = nil, page_all = true) ⇒ Collection
Arguments to the constructor are the current page number, per-page limit the total number of entries, and whether or not to enumerate through all pages. The last two arguments are optional because it is best to do lazy counting; in other words, count conditionally after populating the collection using the replace
method, and because it is assumed that you want to know the total number of pages in your collection.
50 51 52 53 54 55 56 57 58 59 |
# File 'lib/will_mostly_paginate/collection.rb', line 50 def initialize(page, per_page, total = nil, page_all=true) @current_page = page.to_i raise InvalidPage.new(page, @current_page) if @current_page < 1 @per_page = per_page.to_i raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1 @page_all = page_all @next_exists = true # Worst case, we'll get an empty page... self.total_entries = total if total end |
Instance Attribute Details
#current_page ⇒ Object (readonly)
Returns the value of attribute current_page.
41 42 43 |
# File 'lib/will_mostly_paginate/collection.rb', line 41 def current_page @current_page end |
#next_exists ⇒ Object
Returns the value of attribute next_exists.
42 43 44 |
# File 'lib/will_mostly_paginate/collection.rb', line 42 def next_exists @next_exists end |
#page_all ⇒ Object (readonly)
Returns the value of attribute page_all.
41 42 43 |
# File 'lib/will_mostly_paginate/collection.rb', line 41 def page_all @page_all end |
#per_page ⇒ Object (readonly)
Returns the value of attribute per_page.
41 42 43 |
# File 'lib/will_mostly_paginate/collection.rb', line 41 def per_page @per_page end |
#total_entries ⇒ Object
Returns the value of attribute total_entries.
41 42 43 |
# File 'lib/will_mostly_paginate/collection.rb', line 41 def total_entries @total_entries end |
#total_pages ⇒ Object (readonly)
Returns the value of attribute total_pages.
41 42 43 |
# File 'lib/will_mostly_paginate/collection.rb', line 41 def total_pages @total_pages end |
Class Method Details
.create(page, per_page, total = nil, page_all = true) {|pager| ... } ⇒ Object
Just like new
, but yields the object after instantiation and returns it afterwards. This is very useful for manual pagination:
@entries = WillPaginate::Collection.create(1, 10) do |pager|
result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
# inject the result array into the paginated collection:
pager.replace(result)
unless pager.total_entries
# the pager didn't manage to guess the total count, do it manually
pager.total_entries = Post.count
end
end
The possibilities with this are endless. For another example, here is how WillPaginate used to define pagination for Array instances:
Array.class_eval do
def paginate(page = 1, per_page = 15)
WillPaginate::Collection.create(page, per_page, size) do |pager|
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.
88 89 90 91 92 |
# File 'lib/will_mostly_paginate/collection.rb', line 88 def self.create(page, per_page, total = nil, page_all=true) pager = new(page, per_page, total, page_all) yield pager pager end |
Instance Method Details
#next_page ⇒ Object
current_page + 1 or nil if there is no next page
115 116 117 118 119 120 121 |
# File 'lib/will_mostly_paginate/collection.rb', line 115 def next_page if page_all current_page < total_pages ? (current_page + 1) : nil else next_exists ? (current_page + 1) : nil end end |
#offset ⇒ Object
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 side by side with records in the view: simply start with offset + 1.
105 106 107 |
# File 'lib/will_mostly_paginate/collection.rb', line 105 def offset (current_page - 1) * per_page end |
#out_of_bounds? ⇒ Boolean
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.
97 98 99 |
# File 'lib/will_mostly_paginate/collection.rb', line 97 def out_of_bounds? !page_all || current_page > total_pages end |
#previous_page ⇒ Object
current_page - 1 or nil if there is no previous page
110 111 112 |
# File 'lib/will_mostly_paginate/collection.rb', line 110 def previous_page current_page > 1 ? (current_page - 1) : nil end |
#replace(array) ⇒ Object
This is a magic wrapper for the original Array#replace method. It serves for populating the paginated collection after initialization.
Why magic? Because it tries to guess the total number of entries judging by the size of given array. If it is shorter than per_page
limit, then we know we’re on the last page. This trick is very useful for avoiding unnecessary hits to the database to do the counting after we fetched the data for the current page.
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
.
142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/will_mostly_paginate/collection.rb', line 142 def replace(array) 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 |