Class: Tesco::Groceries

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

Overview

You’ll need an API and Developer key from secure.techfortesco.com/tescoapiweb/

Defined Under Namespace

Classes: Aisle, Basket, BasketItem, Department, NoSessionKeyError, NotAuthenticatedError, Offer, Paginated, PaginationError, Product, Products, Shelf, TescoApiError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(developer_key, application_key) ⇒ Groceries

Instantiates a tesco object with your developer and application keys



49
50
51
52
53
# File 'lib/tesco.rb', line 49

def initialize(developer_key,application_key)
  @endpoint = URI.parse('http://www.techfortesco.com/groceryapi_b1/RESTService.aspx')
  @developer_key = developer_key
  @application_key = application_key
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, params = {}) ⇒ Object

If there are any other (ie. new) Tesco API calls this will make them available directly:

An api command ‘SEARCHELECTRONICS’ (if one existed) would be available as #search_electronics(:searchtext => ‘computer’,:parameter1 => ‘an option’)



170
171
172
# File 'lib/tesco.rb', line 170

def method_missing(method,params = {})
  api_request(method.to_s.gsub("_",""),params)
end

Instance Attribute Details

#branch_numberObject (readonly)

Returns the value of attribute branch_number.



46
47
48
# File 'lib/tesco.rb', line 46

def branch_number
  @branch_number
end

#customer_forenameObject (readonly)

Returns the value of attribute customer_forename.



46
47
48
# File 'lib/tesco.rb', line 46

def customer_forename
  @customer_forename
end

#customer_idObject (readonly)

Returns the value of attribute customer_id.



46
47
48
# File 'lib/tesco.rb', line 46

def customer_id
  @customer_id
end

#customer_nameObject (readonly)

Returns the value of attribute customer_name.



46
47
48
# File 'lib/tesco.rb', line 46

def customer_name
  @customer_name
end

#endpointObject

Returns the value of attribute endpoint.



45
46
47
# File 'lib/tesco.rb', line 45

def endpoint
  @endpoint
end

Instance Method Details

#anonymous?Boolean

Are we in anonymous mode?

Returns:

  • (Boolean)


130
131
132
# File 'lib/tesco.rb', line 130

def anonymous?
  !@anonymous_mode
end

#api_request(command, params = {}) ⇒ Object

Send a command to the Tesco API directly using the keys set up already. It will return a parsed version of the direct output from the RESTful service. Status codes other than 0 will still raise errors as usual.

Useful if you want a little more control over the the results, shouldn’t be necessary.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/tesco.rb', line 138

def api_request(command,params = {})
   if @session_key.nil? and command != :login # Do an anonymous login if we're not authenticated
  params.merge!({:sessionkey => @session_key}) if not @session_key.nil?
  params = {
    :command => command,
    :applicationkey => @application_key,
    :developerkey => @developer_key,
    :page => 1 # Will be overwritten by a page in params
  }.merge(params)

  json = Net::HTTP.get(@endpoint.host,@endpoint.path+"?"+params.collect { |k,v| "#{k}=#{URI::escape(v.to_s)}" }.join('&'))

  res = JSON::load(json)
  res[:requestparameters] = params

  case res['StatusCode']
  when 0
    # Everything went well
    return res
  when 200
    raise NotAuthenticatedError
    # TODO: Other status codes
  else
    p res
    raise TescoApiError, "Unknown status code! Something went wrong - sorry"
  end
end

#basketObject

Returns a Basket instance, Tesco API keeps track of the items in your basket in between sessions (TODO: i think!)



89
90
91
# File 'lib/tesco.rb', line 89

def basket
  Basket.new(self)
end

#departmentsObject



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/tesco.rb', line 76

def departments
  @@shelves = []
  api_request(:listproductcategories)['Departments'].collect {|dept|
    dept['Aisles'].each do |aisle|
      aisle['Shelves'].each do |shelf|
        @@shelves.push(Shelf.new(self,shelf))
      end
    end
    Department.new(self,dept)
  }
end

#favouritesObject

List all favourite grocery items (requires a non-anonymous login)



71
72
73
74
# File 'lib/tesco.rb', line 71

def favourites
  raise NotAuthenticatedError if @anonymous_mode
  Products.new(self,api_request(:listfavourites))
end

#login(email = '', password = '') ⇒ Object

Authenticates as the given user or as anonymous with the default parameters. Anonymous login will occur automatically upon any request if a login hasn’t already occured



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/tesco.rb', line 113

def (email = '',password = '')
  res = api_request(:login,:email => email, :password => password)
  @anonymous_mode = (res['ChosenDeliverySlotInfo'] == "Not applicable with anonymous login")
  # TODO:InAmendOrderMode

  # The Tesco API returns "Mrs. Test-Farquharson-Symthe" for CustomerName in anonymous mode, for now I'll not include this in the Ruby library
  if !@anonymous_mode # Not for anonymous mode
    @customer_forename = res['CustomerForename']
    @customer_name = res['CustomerName']
    @customer_id = res['CustomerId']
    @branch_number = res['BranchNumber']
  end
  @session_key = res['SessionKey']
  return true
end

#on_offerObject

List all products currently on offer



66
67
68
# File 'lib/tesco.rb', line 66

def on_offer
  Products.new(self,api_request(:listproductoffers))
end

#products_by_category(shelf_id) ⇒ Object

Lists all the products in the given category, as determined from the shelf id. You’re probably better off using #departments, then #Department#aisles, then #Aisle#shelves then Shelf#products which is an alias for this method.

ie. tesco.departments.aisles.shelves.products

Raises:

  • (ArgumentError)


97
98
99
100
# File 'lib/tesco.rb', line 97

def products_by_category(shelf_id)
  raise ArgumentError, "#{shelf_id} is not a valid Shelf ID" if not shelf_id.to_i > 0
  Products.new(self,api_request(:listproductsbycategory,:category => shelf_id))
end

#search(q) ⇒ Object

Search Tesco’s grocery product listing. Returns a list of Products in a special object that acts like a read-only array.



61
62
63
# File 'lib/tesco.rb', line 61

def search(q)
  Products.new(self,api_request(:productsearch,:searchtext => q))
end

#search_shelves(q) ⇒ Object

A convenience method, this will search all the shelves by name and return an array of Shelf objects that match.

You’ll probably want to send a regexp with the case insensitive tag: /kitchen/i

Raises:

  • (ArgumentError)


105
106
107
108
109
# File 'lib/tesco.rb', line 105

def search_shelves(q)
  raise ArgumentError, "The argument needs to be a Regular Expression." if not q.is_a? Regexp
  departments if not @@shelves.is_a? Array
  @@shelves.select {|shelf| shelf.name =~ q }
end