Class: Tesco::Groceries::Paginated

Inherits:
Object
  • Object
show all
Defined in:
lib/tesco.rb

Overview

A special class that takes care of product pagination automatically. It’ll work like a read-only array for the most part but you can request a specific page with #page and requesting a specific item with #[] will request the required page automatically if it hasn’t already been retrieved and stored within the instance’s cache.

Direct Known Subclasses

Products

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api, res) ⇒ Paginated

Don’t use this yourself!



456
457
458
459
460
461
462
463
464
465
# File 'lib/tesco.rb', line 456

def initialize(api,res) # :nodoc:
  @cached_pages = {}
  @api = api
  # Do the page we've been given (usually the first)
  @cached_pages[res['PageNumber'] || 1] = parse_items(res)
  @pages = res['TotalPageCount'] || 1
  @perpage = res['PageProductCount']
  @length = res['TotalProductCount'] || @perpage
  @params = res[:requestparameters]
end

Instance Attribute Details

#lengthObject (readonly)

Returns the value of attribute length.



454
455
456
# File 'lib/tesco.rb', line 454

def length
  @length
end

#pagesObject (readonly)

Returns the value of attribute pages.



454
455
456
# File 'lib/tesco.rb', line 454

def pages
  @pages
end

Instance Method Details

#[](n) ⇒ Object

Will return the item at the requested index, even if that page hasn’t yet been retreived

Raises:

  • (TypeError)


468
469
470
471
472
473
# File 'lib/tesco.rb', line 468

def [](n)
  raise TypeError, "That isn't a valid array reference" if not (n.is_a? Integer and n >= 0)
  raise PaginationError, "That index exceeds the number of items" if n >= @length
  page_num = (n / @perpage).floor + 1
  page(page_num)[n - page_num * @perpage]
end

#each(pages = :all) ⇒ Object

Akin to Array#each, except you must specify which page, or range of pages, of products you wish to iterate over.

Specifying page = 0 or page = :all will iterate over every item on every page

The items on each page will be passed to your block as they’re retrieved, so you’ll get spurts of output.

NB. This method won’t check your enumberable for each item being a valid page until it’s processed all prior pages.



494
495
496
497
498
499
500
501
502
503
# File 'lib/tesco.rb', line 494

def each(pages = :all)
  pages = (1..@pages) if (pages == :all or pages == 0)
  pages = [pages] if not pages.is_a? Enumerable
  pages.each do |page|
    raise PaginationError, "#{page.inspect} isn't a valid page reference" if not (page.is_a? Integer and page >= 0 and page <= @pages)
    page(page).each do |item|
      yield item
    end
  end
end

#inspectObject



505
506
507
508
509
510
511
512
513
514
515
# File 'lib/tesco.rb', line 505

def inspect
  output = ""
  previous = 0
  @cached_pages.each_pair do |page,content|
    output << ", … #{(page - previous) * @perpage} more …" if (previous + 1) != page
    output << ", " << content.inspect[1..-2]
    previous = page
  end
  output << ", … #{@length - previous * @perpage} more" if previous != @pages
  "[#{output[2..-1]}]"
end

#page(page) ⇒ Object

Will return all the items on the requested page (indeces will be relative to the page). Specifying page = 0 or page = :all will give an array of all items, retrieving all details first This could take a very, vey long time!

Raises:



478
479
480
481
482
483
484
485
# File 'lib/tesco.rb', line 478

def page(page)
  page = 0 if page == :all
  raise PaginationError, "That isn't a valid page reference" if not (page.is_a? Integer and page >= 0 and page <= @pages)
  if !@cached_pages.keys.include?(page)
    @cached_pages[res['PageNumber'] || 1] = parse_items(@api.api_request(nil,@params.merge({:page => page})))
  end
  @cached_pages[page]
end