papercavalier-ruby-aaws 0.8.1

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