ruby-paa 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/example/batch_operation +28 -0
  2. data/example/browse_node_lookup1 +46 -0
  3. data/example/customer_content_lookup1 +27 -0
  4. data/example/customer_content_search1 +21 -0
  5. data/example/example1 +78 -0
  6. data/example/help1 +24 -0
  7. data/example/item_lookup1 +54 -0
  8. data/example/item_lookup2 +56 -0
  9. data/example/item_search1 +30 -0
  10. data/example/item_search2 +37 -0
  11. data/example/item_search3 +23 -0
  12. data/example/list_lookup1 +29 -0
  13. data/example/list_search1 +31 -0
  14. data/example/multiple_operation1 +69 -0
  15. data/example/seller_listing_lookup1 +30 -0
  16. data/example/seller_listing_search1 +29 -0
  17. data/example/seller_lookup1 +45 -0
  18. data/example/shopping_cart1 +42 -0
  19. data/example/similarity_lookup1 +48 -0
  20. data/example/tag_lookup1 +34 -0
  21. data/example/transaction_lookup1 +25 -0
  22. data/example/vehicle_search +22 -0
  23. data/lib/ruby-paa.rb +165 -0
  24. data/lib/ruby-paa/aws.rb +1489 -0
  25. data/lib/ruby-paa/aws/cache.rb +141 -0
  26. data/lib/ruby-paa/aws/search.rb +463 -0
  27. data/lib/ruby-paa/aws/shoppingcart.rb +536 -0
  28. data/lib/ruby-paa/locale.rb +102 -0
  29. data/test/setup.rb +56 -0
  30. data/test/tc_amazon.rb +20 -0
  31. data/test/tc_aws.rb +160 -0
  32. data/test/tc_browse_node_lookup.rb +49 -0
  33. data/test/tc_customer_content_lookup.rb +49 -0
  34. data/test/tc_help.rb +44 -0
  35. data/test/tc_item_lookup.rb +47 -0
  36. data/test/tc_item_search.rb +105 -0
  37. data/test/tc_list_lookup.rb +60 -0
  38. data/test/tc_list_search.rb +44 -0
  39. data/test/tc_multiple_operation.rb +375 -0
  40. data/test/tc_operation_request.rb +64 -0
  41. data/test/tc_seller_listing_lookup.rb +47 -0
  42. data/test/tc_seller_listing_search.rb +55 -0
  43. data/test/tc_seller_lookup.rb +44 -0
  44. data/test/tc_serialisation.rb +107 -0
  45. data/test/tc_shopping_cart.rb +214 -0
  46. data/test/tc_similarity_lookup.rb +48 -0
  47. data/test/tc_tag_lookup.rb +24 -0
  48. data/test/tc_transaction_lookup.rb +24 -0
  49. data/test/tc_vehicle_operations.rb +118 -0
  50. data/test/ts_aws.rb +24 -0
  51. metadata +132 -0
@@ -0,0 +1,536 @@
1
+ # $Id: shoppingcart.rb,v 1.20 2010/02/19 19:13:39 ianmacd Exp $
2
+ #
3
+
4
+ require 'ruby-paa/aws/search'
5
+
6
+ module Amazon
7
+
8
+ module AWS
9
+
10
+ # Load this library with:
11
+ #
12
+ # require 'amazon/aws/shoppingcart'
13
+ #
14
+ module ShoppingCart
15
+
16
+ # Attempts to remove non-existent items from a shopping-cart will raise
17
+ # this exception.
18
+ #
19
+ class CartError < Amazon::AWS::Error::AWSError; end
20
+
21
+ class Cart < Amazon::AWS::Search::Request
22
+
23
+ # _cart_id_ is an alphanumeric token that uniquely identifies a
24
+ # remote shopping-cart. _hmac_ is a <b>H</b>ash <b>M</b>essage
25
+ # <b>A</b>uthentication <b>C</b>ode. This is an encrypted alphanumeric
26
+ # token used to authenticate requests. _purchase_url_ is the URL to
27
+ # follow in order to complete the purchase of the items in the
28
+ # shopping-cart. _cart_items_ is an Array of items in the active area
29
+ # of the cart and _saved_for_later_items_ is an Array of items in the
30
+ # <i>Save For Later</i> area of the cart.
31
+ #
32
+ attr_reader :cart_id, :hmac, :purchase_url, :cart_items, :saved_for_later_items
33
+ alias :items :cart_items
34
+ alias :saved_items :saved_for_later_items
35
+ alias :saved :saved_for_later_items
36
+
37
+
38
+ # Create a new instance of a remote shopping-cart. See
39
+ # Amazon::AWS::Search::Request.new for details of the parameters.
40
+ #
41
+ # Example:
42
+ #
43
+ # cart = Cart.new
44
+ #
45
+ def initialize(key_id=nil, associate=nil, locale=nil,
46
+ user_agent=USER_AGENT)
47
+
48
+ @cart_items = []
49
+ @saved_for_later_items = []
50
+
51
+ # Note the *false* as the fourth parameter to _super_, because we
52
+ # never want to cache shopping-cart transactions.
53
+ #
54
+ super( key_id, associate, locale, false, user_agent )
55
+ end
56
+
57
+
58
+ # Prepare the remote shopping-cart for use and place one or more items
59
+ # in it.
60
+ #
61
+ # _id_type_ is a String, either *ASIN* or *OfferListingId*. _item_id_
62
+ # is the actual ASIN or offer listing ID in question, _quantity_ is
63
+ # the quantity of the item to add to the cart, and _merge_cart_ is
64
+ # whether or not the remote shopping-cart should be merged with the
65
+ # local cart on the Amazon retail site upon check-out.
66
+ #
67
+ # _more_items_ is an optional list of Hash objects describing
68
+ # additional items to place in the cart.
69
+ #
70
+ # Example:
71
+ #
72
+ # cart.cart_create( :ASIN, 'B00151HZA6', 1,
73
+ # { 'B000WC4AH0' => 2 },
74
+ # { 'B000PY32OM' => 3 } )
75
+ #
76
+ # or:
77
+ #
78
+ # cart.cart_create( :ASIN, 'B00151HZA6', 1,
79
+ # { 'B000WC4AH0' => 2,
80
+ # 'B000PY32OM' => 3 } )
81
+ #
82
+ # Please note that it's not yet possible to update a wishlist at
83
+ # purchase time by referring to the item's *ListItemId* when adding
84
+ # that item to the cart.
85
+ #
86
+ def cart_create(id_type, item_id, quantity=1, merge_cart=false,
87
+ *more_items)
88
+ cc = CartCreate.new( id_type, item_id, quantity, merge_cart, nil,
89
+ *more_items )
90
+
91
+ @rg = ResponseGroup.new( :Cart )
92
+ cc.response_group = @rg
93
+
94
+ cart = search( cc ).cart_create_response.cart
95
+
96
+ @cart_id = cart.cart_id
97
+ @hmac = cart.hmac
98
+ @purchase_url = cart.purchase_url
99
+ @cart_items = cart.cart_items.cart_item
100
+ end
101
+
102
+ alias :create :cart_create
103
+
104
+
105
+ # Add one or more new items to the remote shopping-cart. This can not
106
+ # be used to update quantities of items *already* in the cart. For
107
+ # that, you must use Cart#cart_modify instead.
108
+ #
109
+ # _id_type_ is a String, either *ASIN* or *OfferListingId*. _item_id_
110
+ # is the actual ASIN or offer listing ID in question, and _quantity_
111
+ # is the quantity of the item to add to the cart.
112
+ #
113
+ # _more_items_ is an optional list of Hash objects describing
114
+ # additional items to add to the cart.
115
+ #
116
+ # Example:
117
+ #
118
+ # cart.cart_add( :ASIN, 'B0014C2BL4', 3,
119
+ # { 'B00006BCKL' => 2 },
120
+ # { 'B000VVE2UW' => 1 } )
121
+ #
122
+ # or:
123
+ #
124
+ # cart.cart_add( :ASIN, 'B0014C2BL4', 3,
125
+ # { 'B00006BCKL' => 2,
126
+ # 'B000VVE2UW' => 1 } )
127
+ #
128
+ def cart_add(id_type, item_id, quantity=1, *more_items)
129
+ ca = CartAdd.new( id_type, item_id, quantity, *more_items )
130
+ ca.response_group = @rg
131
+ ca.params.merge!( { 'CartId' => @cart_id, 'HMAC' => @hmac } )
132
+
133
+ cart = search( ca ).cart_add_response.cart
134
+ @cart_items = cart.cart_items.cart_item
135
+ end
136
+
137
+ alias :add :cart_add
138
+
139
+
140
+ # Returns whether or not an item is present in the cart, be it in the
141
+ # active or <i>Save For Later</i> area.
142
+ #
143
+ # _item_id_type_ is the name of the attribute that uniquely identifies
144
+ # an item, such as *ASIN* or *CartItemId*. _item_id_ is the value of
145
+ # the _item_id_type_ for the item whose presence in the cart is being
146
+ # determined.
147
+ #
148
+ # If the item is present in the cart, its _CartItemId_ is returned as a
149
+ # String. Otherwise, *false* is returned.
150
+ #
151
+ # Example:
152
+ #
153
+ # cart.include?( :ASIN, 'B00151HZA6' )
154
+ #
155
+ def include?(item_id_type, item_id)
156
+ active?( item_id_type, item_id ) ||
157
+ saved_for_later?( item_id_type, item_id )
158
+ end
159
+
160
+ alias :contain? :include?
161
+
162
+
163
+ # Returns whether or not an item is present in an area of the cart.
164
+ #
165
+ # _area_ is an array of cart items, _item_id_type_ is the name of the
166
+ # attribute that uniquely identifies an item, such as *ASIN* or
167
+ # *CartItemId* and _item_id_ is the value of the _item_id_type_ for
168
+ # the item whose presence in the cart is being determined.
169
+ #
170
+ # If the item is present in the cart, its _CartItemId_ is returned as a
171
+ # String. Otherwise, *false* is returned.
172
+ #
173
+ # Example:
174
+ #
175
+ # cart.in_area?( @cart_items, :ASIN, 'B00151HZA6' )
176
+ #
177
+ # or:
178
+ #
179
+ # cart.in_area?( @saved_for_later_items, :ASIN, 'B00151HZA6' )
180
+ #
181
+ def in_area?(area, item_id_type, item_id)
182
+ found = area.find do |item|
183
+ item.send( Amazon.uncamelise( item_id_type.to_s ) ).to_s == item_id
184
+ end
185
+
186
+ found ? found.cart_item_id.to_s : false
187
+ end
188
+ private :in_area?
189
+
190
+
191
+ # Returns whether or not an item is present in the active area of the
192
+ # cart.
193
+ #
194
+ # _item_id_type_ is the name of the attribute that uniquely identifies
195
+ # an item, such as *ASIN* or *CartItemId*. _item_id_ is the value of
196
+ # the _item_id_type_ for the item whose presence in the cart is being
197
+ # determined.
198
+ #
199
+ # If the item is present in the cart, its _CartItemId_ is returned as a
200
+ # String. Otherwise, *false* is returned.
201
+ #
202
+ # Example:
203
+ #
204
+ # cart.active?( :ASIN, 'B00151HZA6' )
205
+ #
206
+ def active?(item_id_type, item_id)
207
+ in_area?( @cart_items, item_id_type, item_id )
208
+ end
209
+
210
+
211
+ # Returns whether or not an item is present in the <i>Save For
212
+ # Later</i> area of the cart.
213
+ #
214
+ # _item_id_type_ is the name of the attribute that uniquely identifies
215
+ # an item, such as *ASIN* or *CartItemId*. _item_id_ is the value of
216
+ # the _item_id_type_ for the item whose presence in the cart is being
217
+ # determined.
218
+ #
219
+ # If the item is present in the cart, its _CartItemId_ is returned as a
220
+ # String. Otherwise, *false* is returned.
221
+ #
222
+ # Example:
223
+ #
224
+ # cart.saved_for_later?( :ASIN, 'B00151HZA6' )
225
+ #
226
+ def saved_for_later?(item_id_type, item_id)
227
+ in_area?( @saved_for_later_items, item_id_type, item_id )
228
+ end
229
+
230
+ alias :saved? :saved_for_later?
231
+
232
+
233
+ # Modify the quantities of one or more products already in the cart.
234
+ # Changing the quantity of an item to <b>0</b> effectively removes it
235
+ # from the cart.
236
+ #
237
+ # _item_id_type_ is the name of the attribute that uniquely identifies
238
+ # an item in the cart, such as *ASIN* or *CartItemId*. _item_id_ is
239
+ # the value of the _item_id_type_ of the item to be modified, and
240
+ # _quantity_ is its new quantity.
241
+ #
242
+ # _save_for_later_ should be set to *true* if the items in question
243
+ # should be moved to the <i>Save For Later</i> area of the
244
+ # shopping-cart, or *false* if they should be moved to the active
245
+ # area. _save_for_later_ therefore applies to every item specified by
246
+ # _item_id_ and _more_items_. Use *nil* when the location of the items
247
+ # should not be changed.
248
+ #
249
+ # Current Amazon AWS documentation claims that specifying partial
250
+ # quantities can be used to move some copies of an item from one area
251
+ # of the cart to another, whilst leaving the rest in place. In
252
+ # practice, however, this causes an AWS error that explains that a
253
+ # quantity may not be specified in combination with an instruction to
254
+ # move copies from one area of the cart to another. For this reason,
255
+ # when _save_for_later_ is not *nil*, item quantities are currently
256
+ # ignored.
257
+ #
258
+ # _more_items_ is an optional list of Hash objects describing
259
+ # additional items whose quantity should be modified.
260
+ #
261
+ # Example:
262
+ #
263
+ # cart.cart_modify( :ASIN, 'B00151HZA6', 2, false,
264
+ # { 'B0013F2M52' => 1 },
265
+ # { 'B000HCPSR6' => 3 } )
266
+ #
267
+ # or:
268
+ #
269
+ # cart.cart_modify( :ASIN, 'B00151HZA6', 2, true,
270
+ # { 'B0013F2M52' => 1,
271
+ # 'B000HCPSR6' => 3 } )
272
+ #
273
+ def cart_modify(item_id_type, item_id, quantity, save_for_later=nil,
274
+ *more_items)
275
+ item_quantity1 = quantity
276
+
277
+ unless cart_item_id1 = self.include?( item_id_type, item_id )
278
+ raise CartError,
279
+ "Can't find item with '#{item_id_type}' of '#{item_id}' in cart."
280
+ end
281
+
282
+ more_items.collect! do |extra_item|
283
+ items = []
284
+
285
+ extra_item.each do |item|
286
+ item_id, quantity = item
287
+ unless cart_item_id = self.include?( item_id_type, item_id )
288
+ raise CartError,
289
+ "Can't find item with '#{item_id_type}' of '#{item_id}' in cart."
290
+ end
291
+
292
+ items << { cart_item_id => quantity }
293
+ end
294
+
295
+ items
296
+ end
297
+
298
+ more_items.flatten!
299
+
300
+ cm = CartModify.new( cart_item_id1, item_quantity1, save_for_later,
301
+ *more_items )
302
+ cm.response_group = @rg
303
+ cm.params.merge!( { 'CartId' => @cart_id, 'HMAC' => @hmac } )
304
+
305
+ cart = search( cm ).cart_modify_response.cart
306
+
307
+ if ci = cart.cart_items
308
+ @cart_items = ci.cart_item
309
+ else
310
+ @cart_items = []
311
+ end
312
+
313
+ if sfl = cart.saved_for_later_items
314
+ @saved_for_later_items = sfl.saved_for_later_item
315
+ else
316
+ @saved_for_later_items = []
317
+ end
318
+ end
319
+
320
+ alias :modify :cart_modify
321
+
322
+
323
+ # Retrieve a remote shopping-cart. This is especially useful when
324
+ # needing to resurrect a cart at a later time, when the Cart object
325
+ # containing the original data no longer exists.
326
+ #
327
+ # _cart_id_ is the unique ID of the cart to be retrieved and _hmac_ is
328
+ # the cart's hash message authentication code. These details can
329
+ # be obtained from an existing cart using the <i>@cart_id</i> and
330
+ # <i>@hmac</i> instance variables.
331
+ #
332
+ # Example:
333
+ #
334
+ # old_cart = Cart.new
335
+ # old_cart.get_cart( '203-4219703-7532717',
336
+ # 'o98sn9Z16JOEF/9eo6OcD8zOZA4=' )
337
+ #
338
+ def cart_get(cart_id, hmac)
339
+ cg = CartGet.new
340
+ @rg = ResponseGroup.new( :Cart )
341
+ cg.response_group = @rg
342
+ cg.params.merge!( { 'CartId' => cart_id, 'HMAC' => hmac } )
343
+
344
+ cart = search( cg ).cart_get_response.cart
345
+
346
+ @cart_id = cart.cart_id
347
+ @hmac = cart.hmac
348
+ @purchase_url = cart.purchase_url
349
+
350
+ if ci = cart.cart_items
351
+ @cart_items = ci.cart_item
352
+ else
353
+ @cart_items = []
354
+ end
355
+
356
+ if sfl = cart.saved_for_later_items
357
+ @saved_for_later_items = sfl.saved_for_later_item
358
+ else
359
+ @saved_for_later_items = []
360
+ end
361
+
362
+ self
363
+ end
364
+
365
+ alias :get :cart_get
366
+
367
+
368
+ # Remove all items from the shopping-cart.
369
+ #
370
+ # Example:
371
+ #
372
+ # cart.cart_clear
373
+ #
374
+ def cart_clear
375
+ cc = CartClear.new
376
+ cc.response_group = @rg
377
+ cc.params.merge!( { 'CartId' => @cart_id, 'HMAC' => @hmac } )
378
+
379
+ cart = search( cc ).cart_clear_response.cart
380
+
381
+ @cart_items = []
382
+ @saved_for_later_items = []
383
+
384
+ end
385
+
386
+ alias :clear :cart_clear
387
+
388
+
389
+ include Enumerable
390
+
391
+ # Iterator for each item in the cart.
392
+ #
393
+ def each
394
+ @cart_items.each { |item| yield item }
395
+ end
396
+
397
+ alias :each_item :each
398
+
399
+ end
400
+
401
+
402
+ class CartOperation < Operation # :nodoc:
403
+
404
+ def query_parameters
405
+ @params.merge!( { 'Operation' => @kind,
406
+ 'ResponseGroup' => @response_group } )
407
+ end
408
+
409
+ # Writer method is overridden in parent class, but we want access to
410
+ # the original here, so we unalias it in this class.
411
+ #
412
+ alias :response_group= :response_group_orig=
413
+ end
414
+
415
+
416
+ # Worker class used by Cart#cart_create.
417
+ #
418
+ class CartCreate < CartOperation # :nodoc:
419
+
420
+ # Create a shopping-cart and add item(s) to it.
421
+ #
422
+ def initialize(id_type, item_id, quantity, merge_cart=false,
423
+ save_for_later=nil, *more_items)
424
+
425
+ # FIXME: Need to deal with ListItemId, too.
426
+
427
+ # Prepend first item to more_items array (which may be empty).
428
+ #
429
+ more_items.unshift( { item_id => quantity } )
430
+
431
+ mc = merge_cart ? 'True' : 'False'
432
+
433
+ more_items.collect! do |extra_item|
434
+ items = []
435
+
436
+ extra_item.each do |item|
437
+ item_id, quantity = item
438
+
439
+ case save_for_later
440
+ when true
441
+ items << { id_type => item_id,
442
+ 'Action' => 'SaveForLater' }
443
+ when false
444
+ items << { id_type => item_id,
445
+ 'Action' => 'MoveToCart' }
446
+ when nil
447
+ items << { id_type => item_id,
448
+ 'Quantity' => quantity }
449
+ else
450
+ raise CartError,
451
+ "save_for_later must be true, false or nil, but was #{save_for_later}"
452
+ end
453
+ end
454
+
455
+ items
456
+ end
457
+
458
+ more_items.flatten!
459
+
460
+ # Force batch syntax.
461
+ #
462
+ params = {}
463
+
464
+ more_items.each_with_index do |hash, index|
465
+ hash.each do |k, v|
466
+ shared = 'Item.%d.%s' % [ index + 1, k ]
467
+ params[shared] = v
468
+ end
469
+ end
470
+
471
+ params.merge!( { 'MergeCart' => mc } ) if merge_cart
472
+ super( params )
473
+ end
474
+
475
+ end
476
+
477
+
478
+ # Worker class used by Cart#cart_add.
479
+ #
480
+ class CartAdd < CartCreate # :nodoc:
481
+
482
+ # Add new item(s) to a cart.
483
+ #
484
+ def initialize(id_type, item_id, quantity, *more_items)
485
+ super( id_type, item_id, quantity, false, nil, *more_items )
486
+ end
487
+
488
+ end
489
+
490
+
491
+ # Worker class used by Cart#cart_modify.
492
+ #
493
+ class CartModify < CartCreate # :nodoc:
494
+
495
+ # Modify the quantity of item(s) in a cart.
496
+ #
497
+ def initialize(cart_item_id, quantity, save_for_later=false,
498
+ *more_items)
499
+
500
+ super( 'CartItemId', cart_item_id, quantity, false, save_for_later,
501
+ *more_items )
502
+ end
503
+
504
+ end
505
+
506
+
507
+ # Worker class used by Cart#cart_clear.
508
+ #
509
+ class CartClear < CartOperation # :nodoc:
510
+
511
+ # Remove all items from a cart.
512
+ #
513
+ def initialize
514
+ super( {} )
515
+ end
516
+
517
+ end
518
+
519
+
520
+ # Worker class used by Cart#cart_get.
521
+ #
522
+ class CartGet < CartOperation # :nodoc:
523
+
524
+ # Fetch a cart.
525
+ #
526
+ def initialize
527
+ super( {} )
528
+ end
529
+
530
+ end
531
+
532
+ end
533
+
534
+ end
535
+
536
+ end