module SimplePagination class PageCollection ## # Create a new PageCollection object. The following options are available. # [:current_offset] The zero-based offset of the first record in the current page of results # [:current_page] The one-based offset of the current page of results (alternative to :current_offset) # [:total_records] The total number of results across all pages # [:total_pages] The total number of pages (alternative to :total_records) # [:page_size] The page size # # You can choose between :current_offset and :current_page based on your # needs. Same goes for :total_records and :total_pages. :page_size # is required. # # A typical use of this class would be to define a pages method on your # result set class which returns an instance of PageCollection. (So you can # do, e.g., my_result_set.pages.current and so on.) def initialize(options={}) check_options(options) @pages, @page_size = {}, options[:page_size] @length = options[:total_pages] || (options[:total_records] / @page_size.to_f).ceil @current_page = options[:current_page] || (options[:current_offset]/@page_size)+1 end ## # A Page object representing the page at a given page number (one-based). def [](i) @pages[i] ||= Page.new(i, self) unless out_of_bounds?(i) end ## # A Page object representing the current page in the collection. def current self[@current_page] end ## # A Page object representing the first page in the collection. def first self[1] end ## # A Page object representing the last page in the collection. def last self[length] end ## # The number of pages in the collection. attr_reader :length ## # The number of records shown on each page in the collection. attr_reader :page_size private def check_options(options) raise ArgumentError, "requires :current_offset or :current_page" unless options[:current_offset] || options[:current_page] raise ArgumentError, "requires :page_size" unless options[:page_size] raise ArgumentError, "requires :total_pages or :total_records" unless options[:total_pages] or options[:total_records] end def out_of_bounds?(i) i > length || i < 1 end end end