ordrin 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ordrindemo.rb +323 -0
- data/lib/ordrin/data.rb +148 -0
- data/lib/ordrin/errors.rb +147 -0
- data/lib/ordrin/normalize.rb +186 -0
- data/lib/ordrin/order.rb +79 -0
- data/lib/ordrin/ordrinapi.rb +66 -0
- data/lib/ordrin/restaurant.rb +56 -0
- data/lib/ordrin/user.rb +142 -0
- data/lib/ordrin.rb +58 -0
- metadata +72 -0
data/bin/ordrindemo.rb
ADDED
@@ -0,0 +1,323 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'date'
|
3
|
+
require 'securerandom'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'ordrin'
|
8
|
+
rescue LoadError
|
9
|
+
require 'rubygems'
|
10
|
+
begin
|
11
|
+
require 'ordrin'
|
12
|
+
rescue LoadError
|
13
|
+
require_relative '../lib/ordrin'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module OrdrinDemo
|
18
|
+
#
|
19
|
+
# Global Variables
|
20
|
+
#
|
21
|
+
print "Please input your API key: "
|
22
|
+
STDOUT.flush
|
23
|
+
api_key = gets.chomp
|
24
|
+
|
25
|
+
@@api = Ordrin::APIs.new(api_key, :test)
|
26
|
+
|
27
|
+
# Create an Address object
|
28
|
+
@@address = Ordrin::Data::Address.new('1 Main Street', 'College Station', 'TX', '77840', '(555) 555-5555')
|
29
|
+
@@address_nick = 'addr1'
|
30
|
+
|
31
|
+
# Create a CreditCard object
|
32
|
+
@@first_name = 'Test'
|
33
|
+
@@last_name = 'User'
|
34
|
+
@@credit_card = Ordrin::Data::CreditCard.new("#{@@first_name} #{@@last_name}", '01', (Date.today.year+2).to_s, @@address, '4111111111111111', '123')
|
35
|
+
@@credit_card_nick = 'cc1'
|
36
|
+
|
37
|
+
unique_id = SecureRandom.uuid.to_s.gsub(/-/, '')
|
38
|
+
@@email = "demo+#{unique_id}ruby@ordr.in"
|
39
|
+
@@password = 'password'
|
40
|
+
@@login = Ordrin::Data::UserLogin.new(@@email, @@password)
|
41
|
+
@@alt_first_name = 'Example'
|
42
|
+
@@alt_email = "demo+#{unique_id}rubyalt@ordr.in"
|
43
|
+
@@alt_login = Ordrin::Data::UserLogin.new(@@alt_email, @@password)
|
44
|
+
@@new_password = 'password1'
|
45
|
+
|
46
|
+
#
|
47
|
+
# Restaurant demo functions
|
48
|
+
#
|
49
|
+
|
50
|
+
def OrdrinDemo.delivery_list_immediate_demo()
|
51
|
+
puts "Get a list of restaurants that will deliver if you order now"
|
52
|
+
print "Press enter to execute and see the response"
|
53
|
+
gets
|
54
|
+
delivery_list_immediate = @@api.restaurant.get_delivery_list('ASAP', @@address)
|
55
|
+
PP.pp(delivery_list_immediate)
|
56
|
+
return delivery_list_immediate
|
57
|
+
end
|
58
|
+
|
59
|
+
def OrdrinDemo.delivery_list_future_demo()
|
60
|
+
puts "Get a list of restaurants that will deliver if you order for 12 hours from now"
|
61
|
+
print "Press enter to execute and see the response"
|
62
|
+
gets
|
63
|
+
future_datetime = DateTime.now + 0.5 #A timestamp twelve hours in the future
|
64
|
+
delivery_list_later = @@api.restaurant.get_delivery_list(future_datetime, @@address)
|
65
|
+
PP.pp(delivery_list_later)
|
66
|
+
end
|
67
|
+
|
68
|
+
def OrdrinDemo.delivery_check_demo(restaurant_id)
|
69
|
+
puts "Get whether a particular restaurant will deliver if you order now"
|
70
|
+
print "Press enter to execute and see the response"
|
71
|
+
gets
|
72
|
+
delivery_check = @@api.restaurant.get_delivery_check(restaurant_id, 'ASAP', @@address)
|
73
|
+
PP.pp(delivery_check)
|
74
|
+
end
|
75
|
+
|
76
|
+
def OrdrinDemo.fee_demo(restaurant_id)
|
77
|
+
puts "Get fee and other info for ordering a given amount with a given tip"
|
78
|
+
print "Press enter to execute and see the response"
|
79
|
+
gets
|
80
|
+
subtotal = "$30.00"
|
81
|
+
tip = "$5.00"
|
82
|
+
fee_info = @@api.restaurant.get_fee(restaurant_id, subtotal, tip, 'ASAP', @@address)
|
83
|
+
PP.pp(fee_info)
|
84
|
+
end
|
85
|
+
|
86
|
+
def OrdrinDemo.detail_demo(restaurant_id)
|
87
|
+
puts "Get detailed information about a single restaurant"
|
88
|
+
print "Press enter to execute and see the response"
|
89
|
+
gets
|
90
|
+
restaurant_detail = @@api.restaurant.get_details(restaurant_id)
|
91
|
+
PP.pp(restaurant_detail)
|
92
|
+
return restaurant_detail
|
93
|
+
end
|
94
|
+
|
95
|
+
def OrdrinDemo.find_deliverable_time(restaurant_id)
|
96
|
+
puts "Find a time when this restaurant will deliver"
|
97
|
+
print "Press enter to execute and see the response"
|
98
|
+
gets
|
99
|
+
delivery_check = @@api.restaurant.get_delivery_check(restaurant_id, 'ASAP', @@address)
|
100
|
+
delivery = delivery_check['delivery']
|
101
|
+
if delivery
|
102
|
+
return 'ASAP'
|
103
|
+
end
|
104
|
+
dt = DateTime.now + 1/24.0
|
105
|
+
while not delivery
|
106
|
+
delivery_check = @@api.restaurant.get_delivery_check(restaurant_id, dt, @@address)
|
107
|
+
delivery = delivery_check['delivery']
|
108
|
+
dt += 1/24.0
|
109
|
+
end
|
110
|
+
return dt
|
111
|
+
end
|
112
|
+
#
|
113
|
+
# User demo functions
|
114
|
+
#
|
115
|
+
|
116
|
+
def OrdrinDemo.get_user_demo()
|
117
|
+
puts "Get information about a user"
|
118
|
+
print "Press enter to execute and see the response"
|
119
|
+
gets
|
120
|
+
user_info = @@api.user.get(@@login)
|
121
|
+
PP.pp(user_info)
|
122
|
+
end
|
123
|
+
|
124
|
+
def OrdrinDemo.create_user_demo()
|
125
|
+
puts "Create a user"
|
126
|
+
print "Press enter to execute and see the response"
|
127
|
+
gets
|
128
|
+
response = @@api.user.create(@@login, @@first_name, @@last_name)
|
129
|
+
PP.pp(response)
|
130
|
+
end
|
131
|
+
|
132
|
+
def OrdrinDemo.update_user_demo()
|
133
|
+
puts "Update a user"
|
134
|
+
print "Press enter to execute and see the response"
|
135
|
+
gets
|
136
|
+
response = @@api.user.update(@@login, @@alt_first_name, @@last_name)
|
137
|
+
PP.pp(response)
|
138
|
+
end
|
139
|
+
|
140
|
+
def OrdrinDemo.get_all_addresses_demo()
|
141
|
+
puts "Get a list of all saved addresses"
|
142
|
+
print "Press enter to execute and see the response"
|
143
|
+
gets
|
144
|
+
address_list = @@api.user.get_all_addresses(@@login)
|
145
|
+
PP.pp(address_list)
|
146
|
+
end
|
147
|
+
|
148
|
+
def OrdrinDemo.get_address_demo()
|
149
|
+
puts "Get an address by nickname"
|
150
|
+
print "Press enter to execute and see the response"
|
151
|
+
gets
|
152
|
+
addr = @@api.user.get_address(@@login, @@address_nick)
|
153
|
+
PP.pp(addr)
|
154
|
+
end
|
155
|
+
|
156
|
+
def OrdrinDemo.set_address_demo()
|
157
|
+
puts "Save an address with a nickname"
|
158
|
+
response = @@api.user.set_address(@@login, @@address_nick, @@address)
|
159
|
+
PP.pp(response)
|
160
|
+
end
|
161
|
+
|
162
|
+
def OrdrinDemo.remove_address_demo()
|
163
|
+
puts "Remove a saved address by nickname"
|
164
|
+
print "Press enter to execute and see the response"
|
165
|
+
gets
|
166
|
+
response = @@api.user.remove_address(@@login, @@address_nick)
|
167
|
+
PP.pp(response)
|
168
|
+
end
|
169
|
+
|
170
|
+
def OrdrinDemo.get_all_credit_cards_demo()
|
171
|
+
puts "Get a list of all saved credit cards"
|
172
|
+
credit_card_list = @@api.user.get_all_credit_cards(@@login)
|
173
|
+
PP.pp(credit_card_list)
|
174
|
+
end
|
175
|
+
|
176
|
+
def OrdrinDemo.get_credit_card_demo()
|
177
|
+
puts "Get a saved credit card by nickname"
|
178
|
+
print "Press enter to execute and see the response"
|
179
|
+
gets
|
180
|
+
credit_card = @@api.user.get_credit_card(@@login, @@credit_card_nick)
|
181
|
+
PP.pp(credit_card)
|
182
|
+
end
|
183
|
+
|
184
|
+
def OrdrinDemo.set_credit_card_demo()
|
185
|
+
puts "Save a credit card with a nickname"
|
186
|
+
print "Press enter to execute and see the response"
|
187
|
+
gets
|
188
|
+
response = @@api.user.set_credit_card(@@login, @@credit_card_nick, @@credit_card)
|
189
|
+
PP.pp(response)
|
190
|
+
end
|
191
|
+
|
192
|
+
def OrdrinDemo.remove_credit_card_demo()
|
193
|
+
puts "Remove a saved credit card by nickname"
|
194
|
+
print "Press enter to execute and see the response"
|
195
|
+
gets
|
196
|
+
response = @@api.user.remove_credit_card(@@login, @@credit_card_nick)
|
197
|
+
PP.pp(response)
|
198
|
+
end
|
199
|
+
|
200
|
+
def OrdrinDemo.get_order_history_demo(login)
|
201
|
+
puts "Get a list of all orders made by this user"
|
202
|
+
print "Press enter to execute and see the response"
|
203
|
+
gets
|
204
|
+
order_list = @@api.user.get_order_history(@@login)
|
205
|
+
PP.pp(order_list)
|
206
|
+
end
|
207
|
+
|
208
|
+
def OrdrinDemo.get_order_detail_demo(oid)
|
209
|
+
puts "Get the details of a particular order made by this user"
|
210
|
+
print "Press enter to execute and see the response"
|
211
|
+
gets
|
212
|
+
order_detail = @@api.user.get_order_detail(@@login, oid)
|
213
|
+
PP.pp(order_detail)
|
214
|
+
end
|
215
|
+
|
216
|
+
def OrdrinDemo.set_password_demo()
|
217
|
+
puts "Set a new password for a user"
|
218
|
+
print "Press enter to execute and see the response"
|
219
|
+
gets
|
220
|
+
response = @@api.user.set_password(@@login, @@new_password)
|
221
|
+
PP.pp(response)
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# Order demo functions
|
226
|
+
#
|
227
|
+
|
228
|
+
def OrdrinDemo.anonymous_order_demo(restaurant_id, tray, date_time)
|
229
|
+
puts "Order food as someone without a user account"
|
230
|
+
print "Press enter to execute and see the response"
|
231
|
+
gets
|
232
|
+
tip = Random.rand(500)/100.0
|
233
|
+
response = @@api.order.order(restaurant_id, tray, tip, date_time, @@first_name, @@last_name, @@address, @@credit_card, @@email)
|
234
|
+
PP.pp(response)
|
235
|
+
end
|
236
|
+
|
237
|
+
def OrdrinDemo.create_user_and_order_demo(restaurant_id, tray, date_time)
|
238
|
+
puts "Order food and create an account"
|
239
|
+
print "Press enter to execute and see the response"
|
240
|
+
gets
|
241
|
+
tip = Random.rand(500)/100.0
|
242
|
+
response = @@api.order.order_create_user(restaurant_id, tray, tip, date_time, @@first_name, @@last_name, @@address, @@credit_card, @@alt_email, @@password)
|
243
|
+
PP.pp(response)
|
244
|
+
end
|
245
|
+
|
246
|
+
def OrdrinDemo.order_with_nicks_demo(restaurant_id, tray, date_time)
|
247
|
+
puts "Order food as a logged in user using previously stored address and credit card"
|
248
|
+
print "Press enter to execute and see the response"
|
249
|
+
gets
|
250
|
+
tip = Random.rand(500)/100.0
|
251
|
+
response = @@api.order.order(restaurant_id, tray, tip, date_time, @@first_name, @@last_name, @@address_nick, @@credit_card_nick, nil, @@login)
|
252
|
+
PP.pp(response)
|
253
|
+
return response
|
254
|
+
end
|
255
|
+
|
256
|
+
def OrdrinDemo.find_item_to_order(item_list)
|
257
|
+
for item in item_list
|
258
|
+
if item['is_orderable']=='1'
|
259
|
+
if item['price'].to_f>=5.00
|
260
|
+
return item['id']
|
261
|
+
end
|
262
|
+
else
|
263
|
+
if item.has_key?('children')
|
264
|
+
item_id = find_item_to_order(item['children'])
|
265
|
+
unless item_id.nil?
|
266
|
+
return item_id
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
nil
|
272
|
+
end
|
273
|
+
|
274
|
+
|
275
|
+
#
|
276
|
+
# Main
|
277
|
+
#
|
278
|
+
def OrdrinDemo.run_demo()
|
279
|
+
puts "Run through the entire demo sequence"
|
280
|
+
# Restaurant functions
|
281
|
+
delivery_list = delivery_list_immediate_demo()
|
282
|
+
delivery_list_future_demo()
|
283
|
+
restaurant_id = delivery_list[0]['id']
|
284
|
+
delivery_check_demo(restaurant_id)
|
285
|
+
fee_demo(restaurant_id)
|
286
|
+
detail = detail_demo(restaurant_id)
|
287
|
+
|
288
|
+
# User functions
|
289
|
+
create_user_demo()
|
290
|
+
get_user_demo()
|
291
|
+
update_user_demo()
|
292
|
+
get_user_demo()
|
293
|
+
set_address_demo()
|
294
|
+
get_address_demo()
|
295
|
+
set_credit_card_demo()
|
296
|
+
get_credit_card_demo()
|
297
|
+
|
298
|
+
# Order functions
|
299
|
+
order_date_time = find_deliverable_time(restaurant_id)
|
300
|
+
puts "Ordering food at #{order_date_time}"
|
301
|
+
item_id = find_item_to_order(detail['menu'])
|
302
|
+
item = Ordrin::Data::TrayItem.new(item_id, 10)
|
303
|
+
tray = Ordrin::Data::Tray.new(item)
|
304
|
+
anonymous_order_demo(restaurant_id, tray, order_date_time)
|
305
|
+
order = order_with_nicks_demo(restaurant_id, tray, order_date_time)
|
306
|
+
unless order.nil?
|
307
|
+
get_order_detail_demo(order['refnum'])
|
308
|
+
end
|
309
|
+
|
310
|
+
create_user_and_order_demo(restaurant_id, tray, order_date_time)
|
311
|
+
get_order_history_demo(@@alt_login)
|
312
|
+
|
313
|
+
# Clean up/removing stuff
|
314
|
+
remove_address_demo()
|
315
|
+
get_all_addresses_demo()
|
316
|
+
remove_credit_card_demo()
|
317
|
+
get_all_credit_cards_demo()
|
318
|
+
set_password_demo()
|
319
|
+
#After changing the password I must change the login object to continue to access user info
|
320
|
+
end
|
321
|
+
|
322
|
+
run_demo()
|
323
|
+
end
|
data/lib/ordrin/data.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require_relative 'normalize'
|
3
|
+
module Ordrin
|
4
|
+
module Data
|
5
|
+
# Base class for objects that can save any data with the constructor and then
|
6
|
+
# extract it as a dictionary
|
7
|
+
class OrdrinData
|
8
|
+
# Return a dictionary of particular fields to values, determined per subclass
|
9
|
+
def make_dict
|
10
|
+
dict = {}
|
11
|
+
fields.map {|f| dict[f.to_s]=self.send(f) unless self.send(f).nil?}
|
12
|
+
return dict
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Represents a street address
|
17
|
+
class Address < OrdrinData
|
18
|
+
|
19
|
+
attr_reader :addr, :city, :state, :zip, :phone, :addr2, :fields
|
20
|
+
|
21
|
+
# Store the parts of the address as fields in this object.
|
22
|
+
# Arguments:
|
23
|
+
# addr -- Street address
|
24
|
+
# city -- City
|
25
|
+
# state -- State
|
26
|
+
# zip -- Zip code
|
27
|
+
# phone -- Phone number
|
28
|
+
# addr2 -- Optional second street address line
|
29
|
+
def initialize(addr, city, state, zip, phone, addr2='')
|
30
|
+
@fields = [:addr, :city, :state, :zip, :phone, :addr2]
|
31
|
+
@addr = addr
|
32
|
+
@city = city
|
33
|
+
@state = Normalize.normalize(state, :state)
|
34
|
+
@zip = Normalize.normalize(zip, :zip)
|
35
|
+
@phone = Normalize.normalize(phone, :phone)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Represents information about a credit card
|
40
|
+
class CreditCard < OrdrinData
|
41
|
+
|
42
|
+
attr_reader :expiry_month, :expiry_year, :number, :cvc, :type, :name, :bill_address, :fields
|
43
|
+
|
44
|
+
# Store the credit card info as fields in this object.
|
45
|
+
# Arguments:
|
46
|
+
# name -- The name (first and last) on the credit card
|
47
|
+
# expiry_month -- The month that the card expires (two digits)
|
48
|
+
# expiry_year -- The year that the card expires (four digits)
|
49
|
+
# bill_address -- The billing address. Should be an Ordrin::Data::Address object
|
50
|
+
# number -- The credit card number
|
51
|
+
# cvc -- The card verification number
|
52
|
+
def initialize(name, expiry_month, expiry_year, bill_address, number, cvc)
|
53
|
+
@fields = [:number, :cvc, :expiry_month, :expiry_year, :expiry,
|
54
|
+
:bill_addr, :bill_addr2, :bill_city, :bill_state, :bill_zip,
|
55
|
+
:phone, :name]
|
56
|
+
@expiry_month = Normalize.normalize(expiry_month, :month)
|
57
|
+
@expiry_year = Normalize.normalize(expiry_year, :year)
|
58
|
+
@number, @cvc, @type = Normalize.normalize([number, cvc], :credit_card)
|
59
|
+
@name = name
|
60
|
+
@bill_address = bill_address
|
61
|
+
end
|
62
|
+
|
63
|
+
def bill_addr
|
64
|
+
@bill_address.addr
|
65
|
+
end
|
66
|
+
|
67
|
+
def bill_addr2
|
68
|
+
@bill_address.addr2
|
69
|
+
end
|
70
|
+
|
71
|
+
def bill_city
|
72
|
+
@bill_address.city
|
73
|
+
end
|
74
|
+
|
75
|
+
def bill_state
|
76
|
+
@bill_address.state
|
77
|
+
end
|
78
|
+
|
79
|
+
def bill_zip
|
80
|
+
@bill_address.zip
|
81
|
+
end
|
82
|
+
|
83
|
+
def phone
|
84
|
+
@bill_address.phone
|
85
|
+
end
|
86
|
+
|
87
|
+
# A combination of the expiry_month and expiry_date
|
88
|
+
def expiry
|
89
|
+
"#{expiry_month}/#{expiry_year}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
#Represents a user's login information
|
94
|
+
class UserLogin < OrdrinData
|
95
|
+
|
96
|
+
attr_reader :email, :password, :fields
|
97
|
+
|
98
|
+
# Store the email and password in this object. Saves only the hash of the
|
99
|
+
# password, not the password itself
|
100
|
+
# Arguments:
|
101
|
+
# email -- The user's email address
|
102
|
+
# password -- The user's password (in plain text)
|
103
|
+
def initialize(email, password)
|
104
|
+
@fields = [:email, :password]
|
105
|
+
@email = email
|
106
|
+
@password = UserLogin.hash_password(password)
|
107
|
+
end
|
108
|
+
|
109
|
+
def UserLogin.hash_password(password)
|
110
|
+
return Digest::SHA256.new.hexdigest(password)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Represents a single item in an order
|
115
|
+
class TrayItem
|
116
|
+
|
117
|
+
# Store the descriptors of an order item in this object.
|
118
|
+
# Arguments:
|
119
|
+
# item_id -- the restaurants's numerial ID for the item
|
120
|
+
# quantity -- the quantity
|
121
|
+
# options -- any number of options to apply to the item
|
122
|
+
def initialize(item_id, quantity, *options)
|
123
|
+
@item_id = Normalize.normalize(item_id, :number)
|
124
|
+
@quantity = Normalize.normalize(quantity, :number)
|
125
|
+
@options = options.map {|opt| Normalize.normalize(opt, :number)}
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
"#{@item_id}/#{@quantity},#{@options*','}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Represents a list of items in an order
|
134
|
+
class Tray
|
135
|
+
|
136
|
+
# Store the list of items in this object. Each argument should be of type Item
|
137
|
+
# Arguments:
|
138
|
+
# items -- A list of items to be ordered in this tray
|
139
|
+
def initialize(*items)
|
140
|
+
@items = items
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_s
|
144
|
+
return @items*'+'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Ordrin
|
2
|
+
module Errors
|
3
|
+
# This is the base class for errors specific to this ordrin package
|
4
|
+
class OrdrinError < Exception
|
5
|
+
attr_reader :msg
|
6
|
+
|
7
|
+
def initialize(msg=nil)
|
8
|
+
@msg = msg
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# This error encapsulates an API error returned by the server.
|
13
|
+
class ApiError < OrdrinError
|
14
|
+
attr_reader :text
|
15
|
+
def initialize(msg=nil, text=nil)
|
16
|
+
super(msg)
|
17
|
+
@text = text
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"ApiError(msg='#{msg}', text='#{text}')"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# This error indicates that the server returned a response that could not be
|
26
|
+
# parsed into JSON
|
27
|
+
class ApiInvalidResponseError < OrdrinError
|
28
|
+
def to_s
|
29
|
+
"ApiInvalidResponseError(msg='#{msg}')"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def Errors.state
|
34
|
+
lambda do |value|
|
35
|
+
ArgumentError.new("State must be a two letter postal code abbreviation: #{value}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def Errors.money
|
40
|
+
lambda do |value|
|
41
|
+
ArgumentError.new("Money must be dollars.cents: #{value}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def Errors.zip
|
46
|
+
lambda do |value|
|
47
|
+
ArgumentError.new("Zip code must be exactly 5 digits: #{value}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def Errors.phone
|
52
|
+
lambda do |value|
|
53
|
+
ArgumentError.new("Phone numbers must have exactly 10 digits: #{value}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def Errors.number
|
58
|
+
lambda do |value|
|
59
|
+
ArgumentError.new("This value must be only digits: #{value}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def Errors.month
|
64
|
+
lambda do |value|
|
65
|
+
ArgumentError.new("Months must be two digits: #{value}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def Errors.year
|
70
|
+
lambda do |value|
|
71
|
+
ArgumentError.new("Years must be four digits: #{value}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def Errors.cvc
|
76
|
+
lambda do |value|
|
77
|
+
ArgumentError.new("Credit card CVC must be 3 or 4 digits, depending on the card type: #{value}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def Errors.credit_card
|
82
|
+
lambda do |value|
|
83
|
+
ArgumentError.new("Credit card number must be a valid AmEx, Discover, Mastercard, or Visa card number: #{value}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def Errors.email
|
88
|
+
lambda do |value|
|
89
|
+
ArgumentError.new("Bad email format: #{value}")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def Errors.normalizer
|
94
|
+
lambda do |value|
|
95
|
+
ArgumentError.new("Unknown validator name: #{value}")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def Errors.nick
|
100
|
+
lambda do |value|
|
101
|
+
ArgumentError.new("Nick names can only have letters, nubmers, dashes, and underscores: #{value}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def Errors.date_time
|
106
|
+
lambda do |value|
|
107
|
+
ArgumentError.new("date_time must be a datetime.datetime object or the string 'ASAP': #{value}")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def Errors.date
|
112
|
+
lambda do |value|
|
113
|
+
ArgumentError.new("date must be a datetime.datetime or datetime.date object or the string 'ASAP': #{value}")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def Errors.time
|
118
|
+
lambda do |value|
|
119
|
+
ArgumentError.new("time must be a datetime.datetime or datetime.time object: #{value}")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def Errors.url
|
124
|
+
lambda do |value|
|
125
|
+
ArgumentError.new("url must be a proper url: #{value}")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def Errors.method
|
130
|
+
lambda do |value|
|
131
|
+
ArgumentError.new("method must be a word: #{value}")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def Errors.alphanum
|
136
|
+
lambda do |value|
|
137
|
+
ArgumentError.new("This value must be alphanumeric: #{value}")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def Errors.request_method
|
142
|
+
lambda do |value|
|
143
|
+
ApiError.new("Method not a valid HTTP request method: #{value}")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
|
3
|
+
module Ordrin
|
4
|
+
module Normalize
|
5
|
+
class Normalizers
|
6
|
+
private
|
7
|
+
def regex(regex, error)
|
8
|
+
lambda do |value|
|
9
|
+
result = value.to_s[regex]
|
10
|
+
if result.nil?
|
11
|
+
raise error[value]
|
12
|
+
else
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
public
|
19
|
+
def phone(phone_number)
|
20
|
+
#strips out everything but digits from the phone number
|
21
|
+
phone = phone_number.to_s.gsub(/\D/, '')
|
22
|
+
if phone.length == 10
|
23
|
+
phone[/^(\d{3})(\d{3})(\d{4})$/]
|
24
|
+
"#{$1}-#{$2}-#{$3}"
|
25
|
+
else
|
26
|
+
raise Errors.phone[phone_number]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def money(money)
|
31
|
+
value = money.to_s.gsub(/,/, '')[/^\$?(\d+(\.\d+)?)$/, 1]
|
32
|
+
if value.nil?
|
33
|
+
raise Errors.money[money]
|
34
|
+
else
|
35
|
+
value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def datetime(date_time)
|
40
|
+
if date_time.to_s.upcase == 'ASAP'
|
41
|
+
'ASAP'
|
42
|
+
else
|
43
|
+
begin
|
44
|
+
date_time.strftime('%m-%d+%H:%M')
|
45
|
+
rescue NoMethodError
|
46
|
+
raise Errors.date_time[date_time]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def date(date)
|
52
|
+
if date.to_s.upcase == 'ASAP'
|
53
|
+
'ASAP'
|
54
|
+
else
|
55
|
+
begin
|
56
|
+
date.strftime('%m-%d')
|
57
|
+
rescue NoMethodError
|
58
|
+
raise Errors.date[date_time]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def time(time)
|
64
|
+
if time.to_s.upcase == 'ASAP'
|
65
|
+
'ASAP'
|
66
|
+
else
|
67
|
+
begin
|
68
|
+
time.strftime('%m-%d+%H:%M')
|
69
|
+
rescue NoMethodError
|
70
|
+
raise Errors.time[date_time]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def url(url)
|
76
|
+
url.to_s[/^(https?:\/\/)[-\w.~]+(:\d+)?(\/[-\w.~]+)*/]
|
77
|
+
end
|
78
|
+
|
79
|
+
def state(state)
|
80
|
+
state = state.to_s[/^[A-Za-z]{2}$/]
|
81
|
+
if state.nil?
|
82
|
+
raise Errors.state[state]
|
83
|
+
else
|
84
|
+
state.upcase
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def cc_type(cc_number)
|
90
|
+
cc_map = {'American Express' => /^3[47]\d{13}$/,
|
91
|
+
'Visa' => /^4\d{12}(?:\d{3})?$/,
|
92
|
+
'Mastercard' => /^5[1-5]\d{14}$/,
|
93
|
+
'Discover' => /^6(?:011|5\d{2})\d{12}$/}
|
94
|
+
|
95
|
+
type = nil
|
96
|
+
cc_map.each {|key, value| type = key unless cc_number[value].nil?}
|
97
|
+
type
|
98
|
+
end
|
99
|
+
|
100
|
+
def luhn_checksum(card_number)
|
101
|
+
digits = card_number.to_s.scan(/./).map(&:to_i)
|
102
|
+
checksum = 0
|
103
|
+
digits.each_index do |index|
|
104
|
+
digit = digits[index]
|
105
|
+
if (digits.length-index)%2==1
|
106
|
+
checksum += digit
|
107
|
+
else
|
108
|
+
checksum += 2 * digit
|
109
|
+
end
|
110
|
+
end
|
111
|
+
checksum % 10
|
112
|
+
end
|
113
|
+
|
114
|
+
def luhn_valid?(card_number)
|
115
|
+
luhn_checksum(card_number) == 0
|
116
|
+
end
|
117
|
+
|
118
|
+
public
|
119
|
+
def credit_card(values)
|
120
|
+
number, cvc = values
|
121
|
+
num = number.to_s.gsub(/\D/, '')
|
122
|
+
unless luhn_valid?(num)
|
123
|
+
raise Errors.credit_card[number]
|
124
|
+
end
|
125
|
+
card_type = cc_type(num)
|
126
|
+
if card_type.nil?
|
127
|
+
raise Errors.credit_card[number]
|
128
|
+
else
|
129
|
+
if card_type=='American Express'
|
130
|
+
cvc_length = 4
|
131
|
+
else
|
132
|
+
cvc_length = 3
|
133
|
+
end
|
134
|
+
if cvc.length == cvc_length and !cvc.to_s[/^\d+$/].nil?
|
135
|
+
[num, cvc, card_type]
|
136
|
+
else
|
137
|
+
raise Errors.cvc[cvc]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def unchecked(value)
|
143
|
+
value.to_s
|
144
|
+
end
|
145
|
+
|
146
|
+
def name(value)
|
147
|
+
unchecked(value)
|
148
|
+
end
|
149
|
+
|
150
|
+
def zip(zip)
|
151
|
+
regex(/^\d{5}$/, Errors.zip)[zip]
|
152
|
+
end
|
153
|
+
|
154
|
+
def number(num)
|
155
|
+
regex(/^\d+/, Errors.number)[num]
|
156
|
+
end
|
157
|
+
|
158
|
+
def year(year)
|
159
|
+
regex(/^\d{4}$/, Errors.year)[year]
|
160
|
+
end
|
161
|
+
|
162
|
+
def month(mon)
|
163
|
+
regex(/^\d{2}$/, Errors.month)[mon]
|
164
|
+
end
|
165
|
+
|
166
|
+
def email(email)
|
167
|
+
regex(/^[^@\s]+@[^@\s]+\.[a-zA-Z]{2,3}/, Errors.email)[email]
|
168
|
+
end
|
169
|
+
|
170
|
+
def nick(nick)
|
171
|
+
regex(/^[-\w]+/, Errors.nick)[nick]
|
172
|
+
end
|
173
|
+
|
174
|
+
def alphanum(value)
|
175
|
+
regex(/^[a-zA-Z\d]+$/, Errors.alphanum)[value]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
@@normalizer = Normalizers.new
|
180
|
+
|
181
|
+
public
|
182
|
+
def Normalize.normalize(value, normalizer)
|
183
|
+
@@normalizer.send(normalizer, value)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/ordrin/order.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative 'ordrinapi'
|
2
|
+
require_relative 'normalize'
|
3
|
+
require_relative 'data'
|
4
|
+
|
5
|
+
module Ordrin
|
6
|
+
# This class will be used to access the order API. All return values
|
7
|
+
# are documented at http://ordr.in/developers/order
|
8
|
+
class OrderApi < OrdrinApi
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
#Put all of the data that needs to be passed to the POST request normalized into a dict.
|
13
|
+
def build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login=nil)
|
14
|
+
data = {'restaurant_id' => Normalize.normalize(restaurant_id, :number),
|
15
|
+
'tray' => tray.to_s,
|
16
|
+
'tip' => Normalize.normalize(tip, :money),
|
17
|
+
'delivery_date' => Normalize.normalize(delivery_date_time, :date)}
|
18
|
+
if data['delivery_date'] != 'ASAP'
|
19
|
+
data['delivery_time'] = Normalize.normalize(delivery_date_time, :time)
|
20
|
+
end
|
21
|
+
data['first_name'] = Normalize.normalize(first_name, :name)
|
22
|
+
data['last_name'] = Normalize.normalize(last_name, :name)
|
23
|
+
begin
|
24
|
+
data.merge!(address.make_dict)
|
25
|
+
rescue NoMethodError=>e
|
26
|
+
data['nick'] = Normalize.normalize(address, :nick)
|
27
|
+
end
|
28
|
+
if login.nil?
|
29
|
+
data['em'] = Normalize.normalize(email, :email)
|
30
|
+
end
|
31
|
+
begin
|
32
|
+
credit_card.make_dict.each_pair do |key, value|
|
33
|
+
data["card_#{key}"] = value
|
34
|
+
end
|
35
|
+
rescue NoMethodError=>e
|
36
|
+
data['card_nick'] = Normalize.normalize(credit_card, :nick)
|
37
|
+
end
|
38
|
+
data['type'] = 'res'
|
39
|
+
return data
|
40
|
+
end
|
41
|
+
|
42
|
+
public
|
43
|
+
# Place an order, either anonymously or as a logged in user. At least one
|
44
|
+
# of email and login must be passed. If both are passed, email will be ignored.
|
45
|
+
# Arguments:
|
46
|
+
# restaurant_id -- Ordr.in's restaurant identifier
|
47
|
+
# tray -- A tray of food to order. Should be an ordrin.data.Tray object
|
48
|
+
# tip -- The tip amount
|
49
|
+
# delivery_date_time -- Either 'ASAP' or a datetime object in the future
|
50
|
+
# first_name -- The orderer's first name
|
51
|
+
# last_name -- The orderer's last name
|
52
|
+
# address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
|
53
|
+
# credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
|
54
|
+
# email -- The email address of an anonymous user
|
55
|
+
# login -- The logged in user's login information. Should be an ordrin.data.UserLogin object
|
56
|
+
def order(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email=nil, login=nil)
|
57
|
+
data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, login)
|
58
|
+
return call_api(:post, ['o', restaurant_id], login, data)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Place an order and create a user account
|
62
|
+
# Arguments:
|
63
|
+
# restaurant_id -- Ordr.in's restaurant identifier
|
64
|
+
# tray -- A tray of food to order. Should be an ordrin.data.Tray object
|
65
|
+
# tip -- The tip amount
|
66
|
+
# delivery_date_time -- Either 'ASAP' or a datetime object in the future
|
67
|
+
# first_name -- The orderer's first name
|
68
|
+
# last_name -- The orderer's last name
|
69
|
+
# address -- An address object (Ordrin::Data::Address) or the nickname of a saved address
|
70
|
+
# credit_card -- A credit card object (Ordrin::Data::CreditCard) or the nickname of a saved credit card
|
71
|
+
# email -- The email address of the user
|
72
|
+
# password -- The user's password (in plain text)
|
73
|
+
def order_create_user(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email, password)
|
74
|
+
data = build_dict(restaurant_id, tray, tip, delivery_date_time, first_name, last_name, address, credit_card, email)
|
75
|
+
data['pw'] = Data::UserLogin.hash_password(password)
|
76
|
+
return call_api(:post, ['o', restaurant_id], nil, data)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative 'normalize'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
require 'digest'
|
5
|
+
|
6
|
+
module Ordrin
|
7
|
+
# A base object for calling one part of the ordr.in API
|
8
|
+
class OrdrinApi
|
9
|
+
|
10
|
+
attr_reader :base_url
|
11
|
+
|
12
|
+
# Save the url and key parameters in the object
|
13
|
+
# Arguments:
|
14
|
+
# key -- The developer's API key
|
15
|
+
# base_url -- the url that all API call urls will expand from
|
16
|
+
def initialize(key, base_url)
|
17
|
+
@key = key
|
18
|
+
@base_url = Normalize.normalize(base_url, :url)
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# Calls the api at the saved url and returns the return value as Python data structures.
|
24
|
+
# Rethrows any api error as a Ruby exception
|
25
|
+
def call_api(method, arguments, login=nil, data=nil)
|
26
|
+
methods = {:get => Net::HTTP::Get,
|
27
|
+
:post => Net::HTTP::Post,
|
28
|
+
:put => Net::HTTP::Put,
|
29
|
+
:delete => Net::HTTP::Delete}
|
30
|
+
method = methods[method]
|
31
|
+
uri = ('/'+(arguments.collect {|a| URI.encode a.to_s})*'/')
|
32
|
+
full_url = URI.parse(base_url+uri)
|
33
|
+
req = method.new(full_url.request_uri)
|
34
|
+
unless data.nil?
|
35
|
+
req.body = URI.encode_www_form(data)
|
36
|
+
end
|
37
|
+
unless @key.empty?
|
38
|
+
req['X-NAAMA-CLIENT-AUTHENTICATION'] = "id=\"#{@key}\", version=\"1\""
|
39
|
+
end
|
40
|
+
unless login.nil?
|
41
|
+
hash_code = Digest::SHA256.new.hexdigest("#{login.password}#{login.email}#{uri}")
|
42
|
+
req['X-NAAMA-AUTHENTICATION'] = "username=\"#{login.email}\", response=\"#{hash_code}\", version=\"1\""
|
43
|
+
end
|
44
|
+
http = Net::HTTP.new(full_url.host, full_url.port)
|
45
|
+
if full_url.scheme == "https"
|
46
|
+
http.use_ssl = true
|
47
|
+
http.ca_file = File.join(File.dirname(__FILE__), "cacert.pem")
|
48
|
+
end
|
49
|
+
res = http.start {|http| http.request(req)}
|
50
|
+
#error if not OK response
|
51
|
+
res.value
|
52
|
+
result = JSON.parse(res.body)
|
53
|
+
if result.is_a? Hash
|
54
|
+
if result.has_key?('_error') and result['_error']!=0
|
55
|
+
if result.has_key?('text')
|
56
|
+
raise Errors::ApiError.new(result['msg'], result['text'])
|
57
|
+
else
|
58
|
+
raise Errors::ApiError.new(result['msg'])
|
59
|
+
end
|
60
|
+
result
|
61
|
+
end
|
62
|
+
end
|
63
|
+
result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'ordrinapi'
|
2
|
+
require_relative 'normalize'
|
3
|
+
|
4
|
+
module Ordrin
|
5
|
+
# This object's methods access the ordr.in restaurant API. All return values
|
6
|
+
# are documented at http://ordr.in/developers/restaurant
|
7
|
+
class RestaurantApi < OrdrinApi
|
8
|
+
# Get a list of dicts representing restaurants that will deliver to the
|
9
|
+
# given address at the given time.
|
10
|
+
# Arguments:
|
11
|
+
# date_time -- Either 'ASAP' or a datetime object in the future
|
12
|
+
# address -- the address to deliver to. Should be an Ordrin::Data::Address object
|
13
|
+
def get_delivery_list(date_time, address)
|
14
|
+
dt = Normalize.normalize(date_time, :datetime)
|
15
|
+
return call_api(:get, ['dl', dt, address.zip, address.city, address.addr])
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get data about a given restaurant, including whether it will deliver to
|
19
|
+
# the specified address at the specified time
|
20
|
+
# Arguments:
|
21
|
+
# restaurant_id -- Ordr.in's restaurant identifier
|
22
|
+
# date_time -- Either 'ASAP' or a datetime object in the future
|
23
|
+
# address -- the address to deliver to. Should be an Ordrin::Data::Address object
|
24
|
+
def get_delivery_check(restaurant_id, date_time, address)
|
25
|
+
dt = Normalize.normalize(date_time, :datetime)
|
26
|
+
restauant_id = Normalize.normalize(restaurant_id, :number)
|
27
|
+
return call_api(:get, ['dc', restaurant_id, dt, address.zip, address.city, address.addr])
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get data about a given restaurant, including whether it will deliver to
|
31
|
+
# the specified address at the specified time, and what the fee will be on an
|
32
|
+
# order with the given subtotal and tip
|
33
|
+
# Arguments:
|
34
|
+
# restaurant_id -- Ordr.in's restaurant identifier
|
35
|
+
# subtotal -- the subtotal of the order
|
36
|
+
# tip -- the tip on the order
|
37
|
+
# date_time -- Either 'ASAP' or a datetime object in the future
|
38
|
+
# address -- the address to deliver to. Should be an Ordrin::Data::Address object
|
39
|
+
def get_fee(restaurant_id, subtotal, tip, date_time, address)
|
40
|
+
dt = Normalize.normalize(date_time, :datetime)
|
41
|
+
restaurant_id = Normalize.normalize(restaurant_id, :number)
|
42
|
+
subtotal = Normalize.normalize(subtotal, :money)
|
43
|
+
tip = Normalize.normalize(tip, :money)
|
44
|
+
return call_api(:get, ['fee', restaurant_id, subtotal, tip, dt, address.zip, address.city, address.addr])
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get details of the given restaurant, including contact information and
|
48
|
+
# the menu
|
49
|
+
# Arguments:
|
50
|
+
# restaurant_id -- Ordr.in's restaurant identifier
|
51
|
+
def get_details(restaurant_id)
|
52
|
+
restaurant_id = Normalize.normalize(restaurant_id, :number)
|
53
|
+
return call_api(:get, ['rd', restaurant_id])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ordrin/user.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require_relative 'ordrinapi'
|
2
|
+
require_relative 'normalize'
|
3
|
+
require_relative 'data'
|
4
|
+
|
5
|
+
module Ordrin
|
6
|
+
# This class will be used to access the user API. All return values
|
7
|
+
# are documented at http://ordr.in/developers/user
|
8
|
+
class UserApi < OrdrinApi
|
9
|
+
# Gets account information for the user associated with login
|
10
|
+
# Arguments:
|
11
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
12
|
+
def get(login)
|
13
|
+
return call_api(:get, ['u', login.email], login)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates account for the user associated with login. Throws a relevant exception
|
17
|
+
# on failure.
|
18
|
+
# Arguments:
|
19
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
20
|
+
# first_name -- the user's first name
|
21
|
+
# last_name -- the user's last name
|
22
|
+
def create(login, first_name, last_name)
|
23
|
+
data = {'email' => login.email,
|
24
|
+
'first_name' => Normalize.normalize(first_name, :name),
|
25
|
+
'last_name' => Normalize.normalize(last_name, :name),
|
26
|
+
'pw' => login.password}
|
27
|
+
return call_api(:post, ['u', login.email], nil, data)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Updates account for the user associated with login. Throws a relevant exception
|
31
|
+
# on failure.
|
32
|
+
# Arguments:
|
33
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
34
|
+
# first_name -- the user's first name
|
35
|
+
# last_name -- the user's last name
|
36
|
+
def update(login, first_name, last_name)
|
37
|
+
data = {'email' => login.email,
|
38
|
+
'first_name' => Normalize.normalize(first_name, :name),
|
39
|
+
'last_name' => Normalize.normalize(last_name, :name),
|
40
|
+
'pw' => login.password}
|
41
|
+
return call_api(:post, ['u', login.email], login, data)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get a list of all saved addresses for the user associated with login.
|
45
|
+
# Arguments:
|
46
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
47
|
+
def get_all_addresses(login)
|
48
|
+
return call_api(:get, ['u', login.email, 'addrs'], login)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Get a saved address belonging to the logged in user by nickname.
|
52
|
+
# Arguments:
|
53
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
54
|
+
# addr_nick -- the nickname of the address to get
|
55
|
+
def get_address(login, addr_nick)
|
56
|
+
return call_api(:get, ['u', login.email, 'addrs', Normalize.normalize(addr_nick, :nick)], login)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Save an address by nickname for the logged in user
|
60
|
+
# Throws a relevant exception on failure
|
61
|
+
# Arguments:
|
62
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
63
|
+
# addr_nick -- the nickname of the address to save
|
64
|
+
# address -- the address to save. Should be an Ordrin::Data::Address object
|
65
|
+
def set_address(login, addr_nick, address)
|
66
|
+
return call_api(:put, ['u', login.email, 'addrs', Normalize.normalize(addr_nick, :nick)], login, address.make_dict)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Remove an address, saved by the logged in user, by nickname
|
70
|
+
# Throws a relevant exception on failure.
|
71
|
+
# Arguments:
|
72
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
73
|
+
# addr_nick -- the nickname of the address to remove
|
74
|
+
def remove_address(login, addr_nick)
|
75
|
+
return call_api(:delete, ['u', login.email, 'addrs', Normalize.normalize(addr_nick, :nick)], login)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Get a list of all saved credit cards for the user associated with login.
|
79
|
+
# Arguments:
|
80
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
81
|
+
def get_all_credit_cards(login)
|
82
|
+
return call_api(:get, ['u', login.email, 'ccs'], login)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get a saved credit card belonging to the logged in user by nickname.
|
86
|
+
# Arguments:
|
87
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
88
|
+
# card_nick -- the nickname of the credit card to get
|
89
|
+
def get_credit_card(login, card_nick)
|
90
|
+
return call_api(:get, ['u', login.email, 'ccs', Normalize.normalize(card_nick, :nick)], login)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Save an credit card by nickname for the logged in user
|
94
|
+
# Throws a relevant exception on failure
|
95
|
+
# Arguments:
|
96
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
97
|
+
# card_nick -- the nickname of the credit card to save
|
98
|
+
# credit_card -- the credit card to save. Should be an Ordrin::Data::CreditCard object
|
99
|
+
def set_credit_card(login, card_nick, credit_card)
|
100
|
+
card_nick = Normalize.normalize(card_nick, :nick)
|
101
|
+
data = credit_card.make_dict
|
102
|
+
data.merge!(login.make_dict)
|
103
|
+
data['nick'] = card_nick
|
104
|
+
return call_api(:put, ['u', login.email, 'ccs', card_nick], login, data)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Remove an credit card, saved by the logged in user, by nickname
|
108
|
+
# Throws a relevant exception on failure.
|
109
|
+
# Arguments:
|
110
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
111
|
+
# card_nick -- the nickname of the credit card to remove
|
112
|
+
def remove_credit_card(login, card_nick)
|
113
|
+
return call_api(:delete, ['u', login.email, 'ccs', Normalize.normalize(card_nick, :nick)], login)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Get a list of previous orders by the logged in user.
|
117
|
+
# Arguments:
|
118
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
119
|
+
def get_order_history(login)
|
120
|
+
return call_api(:get, ['u', login.email, 'orders'], login)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Get details of a particular previous order by the logged in user.
|
124
|
+
# Arguments:
|
125
|
+
# login -- the user's login information. Should be an Ordrin::Data::UserLogin object
|
126
|
+
# order_id -- The order ID
|
127
|
+
def get_order_detail(login, order_id)
|
128
|
+
return call_api(:get, ['u', login.email, 'orders', Normalize.normalize(order_id, :alphanum)], login)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Change the logged in user's password.
|
132
|
+
# Arguments:
|
133
|
+
# login -- the user's current login information. Should be an Ordrin::Data::UserLogin object
|
134
|
+
# new_password -- the new password (in plain text)
|
135
|
+
def set_password(login, new_password)
|
136
|
+
data = {'email' => login.email,
|
137
|
+
'password' => Data::UserLogin.hash_password(new_password),
|
138
|
+
'previous_password' => login.password}
|
139
|
+
return self.call_api(:put, ['u', login.email, 'password'], login, data)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/ordrin.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative 'ordrin/restaurant'
|
2
|
+
require_relative 'ordrin/user'
|
3
|
+
require_relative 'ordrin/order'
|
4
|
+
require_relative 'ordrin/data'
|
5
|
+
|
6
|
+
module Ordrin
|
7
|
+
class APIs
|
8
|
+
|
9
|
+
attr_reader :restaurant, :user, :order
|
10
|
+
|
11
|
+
# Sets up this module to make API calls. The first argument is the developer's
|
12
|
+
# API key. The other three are the URLs corresponding to the three parts of the api.
|
13
|
+
# No API calls will work until this function is called. API objects will only be
|
14
|
+
# instantiated for URLs that are passed in.
|
15
|
+
|
16
|
+
# Arguments:
|
17
|
+
# api_key -- The developer's API key
|
18
|
+
# servers -- How the server URLs should be set. Must be :production, :test, or :custom
|
19
|
+
# restaurant_url -- The base url for the restaurant API. Can only be set if servers==:custom.
|
20
|
+
# user_url -- The base url for the user API. Can only be set if servers==:custom.
|
21
|
+
# order_url -- The base url for the order API. Can only be set if servers==:custom.
|
22
|
+
def initialize(api_key, servers, restaurant_url=nil, user_url=nil, order_url=nil)
|
23
|
+
@api_key = api_key
|
24
|
+
if servers!=:custom
|
25
|
+
unless restaurant_url.nil? and user_url.nil? and order_url.nil?
|
26
|
+
raise ArgumentError.new("Individual URL parameters can only be set if servers is set to :custom")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
if servers==:production
|
30
|
+
restaurant_url = "https://r.ordr.in/"
|
31
|
+
user_url = "https://u.ordr.in/"
|
32
|
+
order_url = "https://o.ordr.in/"
|
33
|
+
elsif servers==:test
|
34
|
+
restaurant_url = "https://r-test.ordr.in/"
|
35
|
+
user_url = "https://u-test.ordr.in/"
|
36
|
+
order_url = "https://o-test.ordr.in/"
|
37
|
+
elsif servers!=:custom
|
38
|
+
raise ArgumentError.new("servers must be set to :production, :test, or :custom")
|
39
|
+
end
|
40
|
+
unless restaurant_url.nil?
|
41
|
+
@restaurant = RestaurantApi.new(api_key, restaurant_url)
|
42
|
+
end
|
43
|
+
unless user_url.nil?
|
44
|
+
@user = UserApi.new(api_key, user_url)
|
45
|
+
end
|
46
|
+
unless order_url.nil?
|
47
|
+
@order = OrderApi.new(api_key, order_url)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def config
|
52
|
+
return {"API key" => api_key,
|
53
|
+
"Restaurant URL" => @restaurant.base_url,
|
54
|
+
"User URL" => @user.base_url,
|
55
|
+
"Order URL" => @order.base_url}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ordrin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ordr.in
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: json
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.7.3
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.7.3
|
30
|
+
description: Ordrin API wrapper. Used to simplify making calls to the Ordr.in API
|
31
|
+
in Ruby
|
32
|
+
email:
|
33
|
+
- tech@ordr.in
|
34
|
+
executables:
|
35
|
+
- ordrindemo.rb
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- lib/ordrin.rb
|
40
|
+
- lib/ordrin/data.rb
|
41
|
+
- lib/ordrin/errors.rb
|
42
|
+
- lib/ordrin/normalize.rb
|
43
|
+
- lib/ordrin/order.rb
|
44
|
+
- lib/ordrin/ordrinapi.rb
|
45
|
+
- lib/ordrin/restaurant.rb
|
46
|
+
- lib/ordrin/user.rb
|
47
|
+
- bin/ordrindemo.rb
|
48
|
+
homepage: https://github.com/ordrin/api-ruby
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.23
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Ordrin API wrapper
|
72
|
+
test_files: []
|