Class: Cms::Behaviors::Pagination::Collection

Inherits:
Array
  • Object
show all
Defined in:
lib/cms/behaviors/pagination.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(page, per_page, total = nil) ⇒ Collection

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.

Raises:



26
27
28
29
30
31
32
33
# File 'lib/cms/behaviors/pagination.rb', line 26

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
  raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1

  self.total_entries = total if total
end

Instance Attribute Details

#current_pageObject (readonly)

Returns the value of attribute current_page



20
21
22
# File 'lib/cms/behaviors/pagination.rb', line 20

def current_page
  @current_page
end

#per_pageObject (readonly)

Returns the value of attribute per_page



20
21
22
# File 'lib/cms/behaviors/pagination.rb', line 20

def per_page
  @per_page
end

#total_entriesObject

Returns the value of attribute total_entries



20
21
22
# File 'lib/cms/behaviors/pagination.rb', line 20

def total_entries
  @total_entries
end

#total_pagesObject (readonly)

Returns the value of attribute total_pages



20
21
22
# File 'lib/cms/behaviors/pagination.rb', line 20

def total_pages
  @total_pages
end

Class Method Details

.create(page, per_page, total = nil) {|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.

Yields:

  • (pager)


62
63
64
65
66
# File 'lib/cms/behaviors/pagination.rb', line 62

def self.create(page, per_page, total = nil, &block)
  pager = new(page, per_page, total)
  yield pager
  pager
end

Instance Method Details

#next_pageObject

current_page + 1 or nil if there is no next page



89
90
91
# File 'lib/cms/behaviors/pagination.rb', line 89

def next_page
  current_page < total_pages ? (current_page + 1) : nil
end

#offsetObject

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.



79
80
81
# File 'lib/cms/behaviors/pagination.rb', line 79

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.

Returns:

  • (Boolean)


71
72
73
# File 'lib/cms/behaviors/pagination.rb', line 71

def out_of_bounds?
  current_page > total_pages
end

#previous_pageObject

current_page - 1 or nil if there is no previous page



84
85
86
# File 'lib/cms/behaviors/pagination.rb', line 84

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.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/cms/behaviors/pagination.rb', line 110

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