kernow-ruby-aaws 0.5.4 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -1,17 +1,17 @@
1
- $Id: README,v 1.17 2008/10/03 12:00:19 ianmacd Exp $
1
+ $Id: README,v 1.23 2009/06/15 12:07:51 ianmacd Exp $
2
2
 
3
3
 
4
4
  Introduction
5
5
  ------------
6
6
 
7
- Ruby/AWS is a Ruby language library that makes it relatively easy for the
8
- programmer to retrieve information from the popular Amazon Web site via
7
+ Ruby/AWS is a Ruby language library that aims to make it relatively easy for
8
+ the programmer to retrieve information from the popular Amazon Web site via
9
9
  Amazon's Associates Web Services (AWS). In addition to the original amazon.com
10
10
  site, the local sites amazon.co.uk, amazon.de, amazon.fr, amazon.ca and
11
11
  amazon.co.jp are also supported.
12
12
 
13
13
  Development of Ruby/AWS has been quite swift since the appearance of the first
14
- alpha version, 0.0.1, in late March 2008. Although Ruby/AWS shares almost no
14
+ alpha version, 0.0.1, in late March of 2008. Although Ruby/AWS shares almost no
15
15
  code with its now obsolete predecessor, Ruby/Amazon, many lessons were learnt
16
16
  whilst developing that library, and the experience gained has been rolled into
17
17
  Ruby/AWS.
@@ -25,40 +25,50 @@ History and compatibility with Ruby/Amazon
25
25
  ------------------------------------------
26
26
 
27
27
  In the beginning, there was Ruby/Amazon. This library was built around version
28
- 3.x of the Amazon Web Service API and first saw the light of day in 2004. That
29
- version of the Amazon API was known at the time as AWS 3.x.
28
+ 3.x of the Amazon Web Service API and first saw the light of day in January
29
+ 2004. The version of the Amazon API in use at the time was known as AWS 3.x.
30
30
 
31
31
  Amazon later renamed AWS to ECS, or E-Commerce Service, for the launch of
32
- version 4 of the API, a complete overhaul that provided no backward
32
+ version 4 of their API, a complete overhaul that provided no backward
33
33
  compatibility with previous versions. The previous version of the API was
34
34
  thenceforth sometimes referred to as ECS 3.
35
35
 
36
36
  Demonstrating the wisdom and consistency for which large companies are
37
- globally revered, Amazon changed its mind once again in late 2007, reverting
38
- to the familiar name of AWS. This time, however, it was said to stand for
39
- Associates Web Service.
40
-
41
- Since Amazon started offering AWS, the number of Amazon Web APIs has grown.
42
- AWS is now just one of many. It is therefore no longer appropriate to call
43
- this library by a name so general as Ruby/Amazon, because it interfaces only
44
- with AWS. Therefore, the library will be known henceforth as Ruby/AWS.
37
+ renowned, Amazon changed their mind once again in late 2007, reverting to the
38
+ familiar name of AWS. This time, however, it was said to stand for Associates
39
+ Web Service, rather than Amazon Web Service.
40
+
41
+ Since Amazon first made AWS available, the number of Amazon Web APIs has
42
+ grown and AWS is now just one of many. It is therefore no longer appropriate
43
+ to call this library by a name so general as Ruby/Amazon, because it
44
+ provides an interface to just one of the Amazon Web APIs. Therefore, the
45
+ monicker for this library is Ruby/AWS.
46
+
47
+ Unfortunately for Ruby/AWS, Amazon changed the name once again in May 2009,
48
+ referring to it now as the Product Advertising API. Changing Ruby/AWS's name
49
+ would create more confusion than it would mitigate, however, so I'm not about
50
+ to do so. Similarly, I will continue to refer to the Amazon API in question as
51
+ AWS.
45
52
 
46
53
  Ruby/AWS is built around version 4 of the Amazon AWS API, which is
47
54
  fundamentally different to version 3, both in terms of how requests are made
48
- and data returned. The underlying structure of the XML response is radically
49
- changed from previous versions.
55
+ and the data returned. The underlying structure of the XML response has
56
+ radically changed from previous versions.
50
57
 
51
- It has therefore not been possible in Ruby/AWS to retain any level of API
58
+ It has therefore not been practical for Ruby/AWS to retain any level of API
52
59
  compatibility with Ruby/Amazon. Unfortunately, this means that any code
53
- written for Ruby/Amazon will need to be rewritten to work with Ruby/AWS.
60
+ written for Ruby/Amazon will need to be rewritten to work with Ruby/AWS. The
61
+ good news is that, in most cases, this isn't as much work as it might sound.
54
62
 
55
- One small piece of good news is that the /etc/amazonrc and ~/.amazonrc files
56
- used with Ruby/Amazon _are_ compatible with Ruby/AWS. The only change required
57
- for Ruby/AWS is the addition of a 'key_id' parameter, which should contain
58
- your AWS Access Key ID.
63
+ Another bit of good news is that the /etc/amazonrc and ~/.amazonrc files used
64
+ by Ruby/Amazon _are_ compatible with Ruby/AWS. The only change required for
65
+ Ruby/AWS is the addition of the 'key_id' and 'secret_key_id' parameters, which
66
+ should contain your AWS Access Key ID and its secret counterpart. That fact
67
+ notwithstanding, as of version 0.5.0, Ruby/AWS also supports a more flexible,
68
+ locale-specific configuration syntax.
59
69
 
60
70
  Amazon finally decomissioned v3 of the AWS API on 2008-03-31. As a result, the
61
- original Ruby/Amazon library no longer functions.
71
+ original Ruby/Amazon library no longer functions and is therefore obsolete.
62
72
 
63
73
 
64
74
  AWS Access Key ID
@@ -68,35 +78,40 @@ You can obtain an AWS Access Key ID here:
68
78
 
69
79
  https://aws-portal.amazon.com/gp/aws/developer/registration/index.html
70
80
 
71
- Subscription IDs are deprecated by Amazon and, in any case, not supported by
72
- Ruby/AWS. Please obtain and use an AWS Access Key ID instead.
81
+ You may see mention of Subscription IDs at the above location. Subscription
82
+ IDs are deprecated by Amazon and, in any case, not supported by Ruby/AWS.
83
+ Please obtain and use an AWS Access Key ID instead.
73
84
 
74
85
 
75
86
  API version
76
87
  -----------
77
88
 
78
- Ruby/AWS currently requests the 2008-06-26 revision of the AWS API when
89
+ Ruby/AWS currently requests the 2009-03-31 revision of the AWS API when
79
90
  performing its operations:
80
91
 
81
- http://docs.amazonwebservices.com/AWSECommerceService/2008-03-03/DG/
92
+ http://docs.amazonwebservices.com/AWSECommerceService/2009-03-31/DG/
93
+
94
+ However, a different version can be requested via the 'api' parameter in the
95
+ user configuration file.
82
96
 
83
97
 
84
98
  Status and functionality
85
99
  ------------------------
86
100
 
87
- Ruby/AWS is currently alpha code. Amongst other things, this means:
101
+ Ruby/AWS is currently beta software. Amongst other things, this means:
88
102
 
89
- - You will probably encounter _many_ bugs. You will certainly encounter a few.
90
- If you tell me about them, I will endeavour to fix them.
103
+ - You will encounter bugs, but hopefully not too many and none too serious.
104
+ Tell me about them and I will endeavour to fix them.
91
105
 
92
- - The documentation is incomplete, but steadily getting better. Version 0.0.1
93
- had virtually none, so consider yourself lucky.
106
+ - The documentation isn't what it could be, but it's hopefully enough to get
107
+ you up and running.
94
108
 
95
- - Not all features are currently implemented. Others may not be _fully_
96
- implemented. Yet others may not be _properly_ implemented.
109
+ - Not all features are currently implemented. Others may not yet be _fully_
110
+ implemented. Some, I probably haven't even thought of yet. Again, if
111
+ something's missing, tell me, and if it makes sense, I'll add it.
97
112
 
98
- Nevertheless, the AWS v4 API is now more or less fully supported, with only
99
- tiny gaps in the functionality of some operations.
113
+ In spite of this shortcomings, the AWS v4 API is more or less fully
114
+ supported, with only small gaps in the functionality of some operations.
100
115
 
101
116
  Currently implemented operations are:
102
117
 
@@ -123,29 +138,43 @@ Ruby/AWS is currently alpha code. Amongst other things, this means:
123
138
  CartModify
124
139
  CartClear
125
140
 
126
- Version 0.4.0 also adds:
141
+ Version 0.4.0 added the remaining shopping-cart operation, which I had first
142
+ thought superfluous:
127
143
 
128
144
  CartGet
129
145
 
130
- Multiple operations and batch requests are also supported, but not well
131
- tested. Beware of bugs. There appear to also be (undocumented)
132
- Amazon-imposed restrictions on the use of multiple operations and batch
133
- requests, so some experimentation on your part will probably be required to
134
- determine what works and what doesn't.
146
+ Multiple operations are supported, but not well tested (by me, anyway).
147
+
148
+ As of version 0.5.0, batch operations are fully supported, using the
149
+ Operation#batch method.
150
+
151
+ Beware of bugs in this area. Quite apart from any mistakes I've made in the
152
+ implementation, there appear to also be (undocumented) Amazon-imposed
153
+ restrictions on the use of multiple operations and batch requests, so some
154
+ experimentation will be required on your part to determine what works and
155
+ what doesn't.
156
+
157
+ The 2008-08-19 version of the AWS API added the following operations:
158
+
159
+ VehiclePartLookup
160
+ VehiclePartSearch
161
+ VehicleSearch
162
+
163
+ These are supported by Ruby/AWS from version 0.5.0 onwards.
135
164
 
136
165
  - Classes, methods, constants and instance variables may change name in the
137
- future. These various objects may appear from nowhere, change shape, grow,
138
- shrink or disappear entirely. Indeed, this has already happened once in the
139
- evolution from version 0.0.2 to version 0.1.0, breaking existing code in the
140
- process.
166
+ future. New ones may appear from nowhere and existing ones may change shape,
167
+ grow, shrink or disappear without trace. Such fundamental changes will break
168
+ existing code, so I will endeavour to keep them to a minimum.
141
169
 
142
170
  In short, code written to work with this release of Ruby/AWS may stop working
143
- when you upgrade to the next release. In fact, it may even stop working
144
- _during_ this release, because it's possible there are circumstances that
145
- would cause an exception to be raised, that I haven't come across in my
146
- limited testing of the code.
171
+ when you upgrade to the next. In fact, it may even stop working _during_ this
172
+ release cycle, because it's possible there are fatal conditions that I didn't
173
+ encounter in my limited testing of the code. It's also possible that future
174
+ (possibly unannounced) changes made by Amazon will affect Ruby/AWS in
175
+ ways I can't anticipate.
147
176
 
148
- That said, the Ruby/AWS's API is pretty stable at this point in time. I won't
177
+ That said, the Ruby/AWS API is pretty stable at this point in time. I won't
149
178
  break any of the method interfaces without seriously considering the merits of
150
179
  doing so.
151
180
 
@@ -160,24 +189,66 @@ choose between an installation script and a RubyGems installation.
160
189
  Usage
161
190
  -----
162
191
 
163
- First of all, create either /etc/amazonrc or ~/.amazonrc. Its contents should
164
- look something like this:
192
+ First of all, create either /etc/amazonrc or ~/.amazonrc as a plain text file.
193
+ Its contents should look something like this:
165
194
 
166
- key_id = '0Y44V8G41KCQPGF6PTR2'
195
+ # Any line that starts with a hash character is a comment.
196
+ key_id = '0Y44V8G41KCQPGF6XYZ2'
197
+ secret_key_id = 'k+kuddeoQJzUnImC0Hyy21J4xLWQc1hbvfQ+7F1G
167
198
  associate = 'fuzbarorg-21'
199
+ cache = false
168
200
  locale = 'uk'
201
+ encoding = 'iso-8859-15'
202
+
203
+ The ability to include your secret key was a feature added in version 0.6.0 of
204
+ Ruby/AWS. If you choose to do so, your requests to AWS will be signed for
205
+ authentication by the Amazon's servers.
206
+
207
+ Amazon plans to make this practice obligatory as of 15th August 2009, so I
208
+ recommend that you adopt it well ahead of time.
209
+
210
+ When Amazon checks for a valid signature, it does so by comparing its
211
+ computation of the signature with the one supplied by the user. In doing this,
212
+ Amazon uses the UTF-8 representation of parameter values that you supply, even
213
+ if you use a different encoding.
214
+
215
+ In order to have Ruby/AWS properly reencode your strings as UTF-8, you need
216
+ to tell it which encoding you are using. The 'encoding' parameter can be used
217
+ for this, but you can omit it if your strings are already UTF-8, because this
218
+ is the default.
219
+
220
+ As of version 0.5.0 of Ruby/AWS, the following locale-specific configuration
221
+ syntax is also supported:
222
+
223
+ [global]
224
+ key_id = '0Y44V8G41KCQPGF6XYZ2'
225
+ secret_key_id = 'k+kuddeoQJzUnImC0Hyy21J4xLWQc1hbvfQ+7F1G
169
226
  cache = false
227
+ locale = 'uk'
228
+ encoding = 'iso-8859-15'
229
+ # Request a specific version of the API.
230
+ # api = '2008-03-03'
231
+
232
+ [uk]
233
+ associate = 'fuzbarorg-21'
170
234
 
171
- Because you're embedding your key ID in the file, you should protect it (on
172
- UNIX and equivalent systems) by making it mode 0600:
235
+ [us]
236
+ associate = 'fuzbarorg-20'
237
+
238
+ This enables the use of a different associate tag for each locale, although,
239
+ oddly enough, no-one has ever requested this feature.
240
+
241
+ Because you're embedding your personal keys in the file, you should protect it
242
+ (on UNIX and equivalent systems) by making it mode 0600:
173
243
 
174
244
  $ chmod 600 ~/.amazonrc
175
245
 
176
- If you define 'cache' to be 'true', you may also define 'cache_dir' to point
177
- to somewhere other the default, /tmp/amazon.
246
+ If you define 'cache' to be 'true', you may want to also define 'cache_dir' to
247
+ point to somewhere other the default cache directory, /tmp/amazon.
178
248
 
179
249
  If you want to place .amazonrc somewhere other than $HOME, you may set
180
- $AMAZONRCDIR in the environment, as this location is checked prior to $HOME.
250
+ the $AMAZONRCDIR environment variable, as this location is checked prior to
251
+ $HOME.
181
252
 
182
253
  If you're using Windows, $HOME is usually undefined, so a number of additional
183
254
  locations are checked for .amazonrc.
@@ -194,13 +265,13 @@ $AMAZONRCDIR and $HOME are defined, but only the path specified by $HOME
194
265
  contains a file called .amazonrc, it will not be found.
195
266
 
196
267
  If you want the user configuration file to be called something other than
197
- .amazonrc, you may define $AMAZONRCFILE in the environment.
268
+ .amazonrc, you may define the $AMAZONRCFILE environment variable.
198
269
 
199
- Once you have your configuration file, you can get started on your code.
270
+ Once you have your configuration file, you can get started writing your code.
200
271
 
201
- Here's some basic code, indicating how to perform an ItemSearch, probably the
272
+ Here's a basic example, showing how to perform an ItemSearch, probably the
202
273
  most common type of AWS operation. Please see the ./examples subdirectory for
203
- more examples of working code.
274
+ more examples of contrived, but working code.
204
275
 
205
276
  --
206
277
 
@@ -252,18 +323,20 @@ XML to Ruby mapping
252
323
  -------------------
253
324
 
254
325
  Here, I will discuss the mapping of the XML returned from AWS to native Ruby
255
- objects and data.
326
+ objects and data. Note that the XML shown below was that returned at the time
327
+ of writing and may look different to what you would see today if you were to
328
+ execute the same request.
256
329
 
257
- When the following code:
330
+ When this code:
258
331
 
259
- resp = req.search( is, rg )
332
+ resp = req.search( is, rg )
260
333
 
261
334
  was called in the previous section, the following URL was composed and sent to
262
335
  AWS as an HTTP GET operation:
263
336
 
264
337
  http://ecs.amazonaws.co.uk/onca/xml?AWSAccessKeyId=01234567890123456789&AssociateTag=calibanorg-21&Operation=ItemSearch&ResponseGroup=Small&SearchIndex=Books&Service=AWSECommerceService&Title=Ruby&Version=2008-03-03
265
338
 
266
- The following (truncated) AWS XML response was received:
339
+ The following (abbreviated) AWS XML response was received:
267
340
 
268
341
  <ItemSearchResponse>
269
342
  <OperationRequest>
@@ -334,7 +407,7 @@ the following statements would all be true:
334
407
  - ItemAttributes, Author, Manufacturer, ProductGroup and Title would all be
335
408
  dynamically defined subclasses of AWSObject.
336
409
 
337
- - An instance of the ItemAttributes class would be instantiated, with instance
410
+ - An instance of the ItemAttributes class would be created, with instance
338
411
  variables @author, @manufacturer, @product_group and @title.
339
412
 
340
413
  - To each of these instance variables would respectively be assigned an array
@@ -343,13 +416,15 @@ the following statements would all be true:
343
416
  would all be single element arrays, because there's only one instance of
344
417
  each kind of tag in the XML.
345
418
 
346
- - These lowest level objects would have no instance variables, because the
347
- corresponding XML elements contain no children, just a value. These objects
348
- are therefore directly assigned the value of the corresponding XML element.
419
+ - The Author, Manufacturer, ProductGroup and Title objects would have no
420
+ instance variables of their own, because the corresponding XML elements
421
+ have no children, just a value. These objects are therefore directly
422
+ assigned the value in question.
349
423
 
350
- So, if resp is the top level AWSObject created and returned by calling
351
- Amazon::AWS::Search::Request#search on the Request object, and we'd like to
352
- know the ASIN of the first item found, we can refer to this as follows:
424
+ So, if resp is the top level AWSObject created and returned by calling the
425
+ Amazon::AWS::Search::Request#search method of the Request object, and we'd
426
+ like to know the ASIN of the first item found, we can refer to this as
427
+ follows:
353
428
 
354
429
  resp.item_search_response[0].items[0].item[0].asin
355
430
 
@@ -357,101 +432,105 @@ Looking at each component of this chain in turn:
357
432
 
358
433
  - resp is an AWSObject with a single instance variable, @item_search_response.
359
434
  This is because the entire XML response is contained within a single
360
- <ItemSearchResponse> tag pair, so there's nothing else at the top level.
435
+ <ItemSearchResponse> element, so there's nothing else at the top level.
361
436
 
362
437
  - resp.item_search_response is assigned an array of ItemSearchResponse
363
- objects. Because there's only a single <ItemSearchResponse> tag pair in the
438
+ objects. Because there's only a single <ItemSearchResponse> element in the
364
439
  whole document (containing the rest of the XML), the array contains only a
365
440
  single element.
366
441
 
367
442
  - resp.item_search_response[0] has an instance variable, @items, which is
368
443
  assigned an array of Items objects. Here again, only a single element is
369
- created, because there's only one <Items> tag pair in the XML.
444
+ created, because there's only one corresponding <Items> element in the XML.
370
445
 
371
446
  - resp.item_search_response[0].items[0] has an instance variable, @item, which
372
- is an array containing the item(s) returned by the search. It is a
447
+ is an array containing the actual item(s) located by the search. It is a
373
448
  multi-element array, however, because more than one item was found, as
374
449
  represented by the multiple <Item> elements in the XML.
375
450
 
376
451
  The creation of so many single element arrays is unfortunate. It makes user
377
452
  code verboser, uglier and consequently harder to read.
378
453
 
379
- Some such arrays do, in fact, have the potential to be multi-element, because
380
- the corresponding XML tag _can_ appear multiple times in the AWS response. A
381
- book, for example, _may_ have more than one <Author>. Many other types of
382
- array, however, are necessarily single element arrays. The same book, for
383
- example, is unlikely to have more than one <Title>.
454
+ You might wonder why Ruby/AWS doesn't just assign the single element itself,
455
+ rather than the array that contains it.
384
456
 
385
- As another concrete example, an ItemSearch will probably return many <Item>
457
+ The answer is that most of these single-element arrays actually do have the
458
+ potential to be multi-element, because the corresponding XML tag _can_ appear
459
+ multiple times in an AWS response. A book, for example, _may_ have more than
460
+ one <Author>. Many other types of array, however, are necessarily single
461
+ element arrays. That same book, for example, is unlikely to have more than one
462
+ <Title>. This is context-dependent and difficult to define programatically.
463
+
464
+ As another concrete example, an ItemSearch will probably yield many <Item>
386
465
  elements in the <ItemSearchResponse>, but these will invariably be nested in a
387
- single <Items> tag. The @items instance variable of the ItemSearchResponse
388
- object will therefore always have a size of 1.
466
+ single <Items> element. The @items instance variable of the ItemSearchResponse
467
+ object will therefore always be a single-element array.
389
468
 
390
- In other words, the following statements are always true when an ItemSearch
391
- successfully finds items:
469
+ In other words, the following statements are both invariably true when an
470
+ ItemSearch successfully locates items:
392
471
 
393
472
  - resp.item_search_response[0].items.size == 1
394
473
 
395
474
  - resp.item_search_response[0].items[0].item.size >= 1
396
475
 
397
476
  The awkwardness of using such single element arrays is alleviated in Ruby/AWS
398
- by the use of the AWSArray subclass. This ever-so-slightly magic class of
399
- array allows element 0 of single-element arrays to be dereferenced using the
400
- base array name, i.e. without a subscript.
477
+ by the use of the AWSArray subclass. An instance of this class differs from a
478
+ standard array by allowing element 0 of a single-element array to be
479
+ dereferenced using just the array name, i.e. without a subscript.
401
480
 
402
- In other words, a reference to foo.bar will actually return foo[0].bar, so
403
- long as foo.size == 1. Note that this only works because the array instance
404
- itself, foo, has no bar method, so the intention is unambiguous and foo can
405
- pass the call of bar down to foo[0]. foo.size, on the other hand, will
406
- _always_ refer to foo and never to foo[0], because Array#size _is_ an existing
407
- method.
481
+ In other words, a reference to foo.bar will actually return foo[0].bar when
482
+ foo.size == 1. Note that this can only work because the array itself, foo, has
483
+ no bar method, so the intention is unambiguous and foo can delegate the
484
+ invocation of the method to foo[0]. foo.size, on the other hand, will _always_
485
+ invoke foo's bar method, never delegating to foo[0], because of the existence
486
+ of the Array#size method.
408
487
 
409
488
  This allows the ASIN of the first item returned in the above XML to be
410
489
  referred to using the following shorthand:
411
490
 
412
491
  resp.item_search_response.items.item[0].asin
413
492
 
414
- It's worth reiterating that it's still necessary to refer to item[0] using a
415
- subscript in this example, because the <Items> tag in the XML contains
416
- multiple <Item> tags, making item.size > 1.
493
+ It's worth reiterating that it's still necessary in this example to refer to
494
+ item[0] using a subscript, because the <Items> element in the XML contains
495
+ multiple <Item> elements, making item.size > 1.
417
496
 
418
497
  Use this syntactic shorthand to your advantage, but understand when you're
419
- likely to be dealing with a single element array and when a multiple. This
420
- will become apparent as you gain familiarity with AWS v4.
498
+ likely to be dealing with a single element array vs. a multiple. This will
499
+ become apparent as you gain familiarity with AWS v4.
421
500
 
422
- An exception will be thrown if an unknown method is called on a multi-element
423
- array, as it can't be known which element the method invocation should be
424
- passed to. This will almost certainly be the result of an incorrect assumption
425
- that an array contains only a single element when it actually contains
426
- multiple.
501
+ An exception will be raised if an unknown method is called on a multi-element
502
+ array, as it can't be known to which array element the method invocation
503
+ should be delegated. This will almost certainly stem from an incorrect
504
+ assumption that an array contains only a single element when, in actual fact,
505
+ it contains multiple elements.
427
506
 
428
- A further important detail to note is that not all AWS operations in the same
507
+ A further important detail to note is that not all AWS operations of the same
429
508
  class return the same data. For example, an ItemSearch using the Books search
430
- index will return items that, amongst other things, create an ItemAttributes
509
+ index will return items that, amongst other things, have an ItemAttributes
431
510
  object containing further objects of class Author, ISBN, etc. An ItemSearch
432
- using the DVD search index, however, will have no Author or ISBN, but _will_
433
- have a Director and probably one or more Actor objects.
511
+ using the DVD search index, by contrast, will have no Author or ISBN, but
512
+ will likely have a Director and probably one or more Actor objects.
434
513
 
435
514
  Because of the disparity in same-class object attributes, Ruby/AWS returns
436
515
  *nil* when an attempt is made to dereference a non-existent instance variable.
437
- This approach was chosen, because it often cannot be known in advance
438
- precisely which data will be returned by a given search. Returning *nil* for
439
- non-existent attributes means that the user does not have to pepper their code
440
- with exception-handling clauses.
516
+ This approach was chosen because, more often than not, it cannot be known in
517
+ advance precisely which data will be returned by a given search operation.
518
+ Returning *nil* for non-existent attributes saves the user from having to
519
+ pepper their code with exception-handling clauses.
441
520
 
442
521
  For example:
443
522
 
444
- resp.item_search_response[0].items[0].item[0].item_attributes.director
523
+ resp.item_search_response[0].items[0].item[0].item_attributes.director
445
524
 
446
525
  will return *nil* for a book, because there was no corresponding Director
447
526
  element in the XML returned by AWS.
448
527
 
449
528
  Similarly:
450
529
 
451
- resp.item_search_response[0].items[0].item[0].item_attributes.foo_bar
530
+ resp.item_search_response[0].items[0].item[0].item_attributes.foo_bar
452
531
 
453
- will _always_ return *nil* for any item, because no kind of ItemSearch will
454
- ever yield an item with a FooBar attribute.
532
+ will _always_ return *nil* for _any_ item, because no kind of ItemSearch will
533
+ ever yield an item with a FooBar element.
455
534
 
456
535
 
457
536
  Parameter checking
@@ -462,18 +541,19 @@ particular type of search. For example, an ItemSearch can use a Sort parameter
462
541
  with a value of 'titlerank' if the SearchIndex is 'Books'. However, this value
463
542
  wouldn't make much sense in the 'Automotive' SearchIndex.
464
543
 
465
- The very presence of a certain parameter can be illegal in a certain contexts.
466
- For example, specifying the parameter 'Author' with any value would be
544
+ The very presence of a certain parameter can be illegal in certain contexts.
545
+ For example, specifying the parameter 'Author' with _any_ value would be
467
546
  nonsensical in the 'PetSupplies' SearchIndex.
468
547
 
469
548
  To complicate things further, the validity of parameters and their values
470
549
  differs not only by search type, but also by Amazon locale (amazon.com,
471
- amazon.co.uk, amazon.de, etc.) and is prone to change with each minor revision
472
- of the Amazon AWS API.
550
+ amazon.co.uk, amazon.de, etc.) and is prone to change with minor revisions of
551
+ the Amazon AWS API.
473
552
 
474
- Even worse, even the operations themselves can be illegal in some locales.
475
- TransactionLookup operations, for example, don't currently work in the UK
476
- locale, but do work in the US locale.
553
+ Even worse, the operations themselves can be illegal in certain locales.
554
+ TransactionLookup operations, for example, don't work in the UK locale at the
555
+ time of writing, but do work in the US locale. As a rule of thumb, we can say
556
+ that almost everything works in the US locale and _may_ work in others.
477
557
 
478
558
  Ruby/Amazon attempted to track these complex and dynamic relationships to
479
559
  prevent illegal or ineffective operations from being attempted. It was a
@@ -481,54 +561,61 @@ time-consuming and tedious task to track the evolving API (which often changed
481
561
  in subtle ways without prior [or even belated] notice from Amazon), find all
482
562
  of the corner cases and handle undocumented quirks.
483
563
 
484
- With the highly dynamic nature of the Amazon environment, plus the sheer
485
- number of operations, parameters, possible legal values and locales in the AWS
486
- v4 API, this strict approach must track too many combinations and permutations
487
- to be practical. Ruby/AWS therefore no longer tries.
564
+ With the highly dynamic nature of the Amazon environment and its many locales,
565
+ plus the sheer number of operations, parameters and their possibly legal
566
+ values in the AWS v4 API, this strict approach would be completely
567
+ impractical for Ruby/AWS. It therefore doesn't even try.
488
568
 
489
569
  Instead, it's now up to you to ensure that you perform legal operations and
490
- pass in sensible parameters and values for the locale in which you're working.
570
+ pass sensible parameters and values for the locale in which you're working.
571
+ The context is now your responsibility.
491
572
 
492
- Parameter name checking, however, _is_ still performed. For example,
493
- performing an ItemSearch and passing in a 'Keywrds' parameter would generate
494
- an exception, because 'Keywrds' doesn't exist as a parameter in any context.
495
- Here, 'Keywords' was obviously what was intended and a simple typo was made by
496
- the user.
573
+ The one exception to this rule is search index checking for ItemSearch
574
+ operations. Code that attempts to use an invalid SearchIndex will raise an
575
+ exception. The list of allowable search indices can be found in the
576
+ Amazon::AWS::Operation::ItemSearch::SEARCH_INDICES array.
497
577
 
498
- Similarly, the SearchIndex must also actually exist, so 'Music' or 'Beauty'
499
- would be valid, but 'Furniture' or 'MobilePhones' would not, because Amazon
500
- does not (currently) offer such indices.
578
+ Of course, even this check exposes the user to the risk that Amazon may later
579
+ add new search indices, which would continue to be unrecognised and ruled
580
+ invalid by Ruby/AWS until an update was issued. Whilst I have chosen to
581
+ implement this very basic level of checking, it may be removed in the future
582
+ if it becomes impractical to keep it current.
501
583
 
502
- In conclusion, we can say that broad checks are performed to determine whether
503
- a search _could_ conceivably be valid in any context, but it's up to you to
504
- determine whether the search actually _is_ valid in your particular context.
584
+ In short, the validity of what goes into a search operation is your own
585
+ responsibility: garbage in, garbage out.
505
586
 
506
587
  Thankfully, with the AWS Developer Guide at your side, it's largely common
507
588
  sense which parameters and values can be used with each type of search. It's
508
- less obvious when these differ by locale, such as 'Beauty' being a valid
509
- SearchIndex in the 'us' locale, bot not in the 'uk'. AWS unfortunately abounds
510
- with such inconsistencies.
589
+ less obvious when these differ by locale. For example, the 'Beauty'
590
+ SearchIndex was valid in the 'us' locale, but not in the 'uk' locale until the
591
+ 2009-01-06 revision of the AWS API.
592
+
593
+ Unfortunately, AWS abounds with such inconsistencies and they are prone to
594
+ change at any time. Amazon, themselves, seem to struggle to document all of
595
+ these quirks, a situation probably aggravated by the US focus of the AWS
596
+ staff.
511
597
 
512
- The only way to apprise yourself of such quirks is to read Amazon's latest
513
- developer documentation (and closely follow the release notes of each minor
514
- API revision to make sure things haven't changed).
598
+ The only way to apprise yourself of such peculiarities is to read Amazon's
599
+ latest developer documentation (and closely follow the release notes of each
600
+ minor API revision to make sure things haven't changed). If you don't want to
601
+ be exposed to such API changes, use the 'api' parameter in the user
602
+ configuration file to request a particular version of the API.
515
603
 
516
604
  The AWS Developer Connection pages may also be of use to you. In particular,
517
605
  the forum for discussing AWS has proved useful to me over the years:
518
606
 
519
607
  http://developer.amazonwebservices.com/connect/forum.jspa?forumID=9
520
608
 
521
- For those illegal operations that make it through and are passed to the Amazon
522
- servers, the good news is that Amazon carries out extensive request-time
523
- parameter checking in AWS v4 (much better than in v3) and will generate an
524
- error when an illegal set of parameters and values is given. Ruby/AWS will
525
- dynamically generate an exception class for the reported type of error and
526
- raise an exception of that class.
609
+ For those illegal operations that make it through to the Amazon servers, the
610
+ good news is that Amazon carries out extensive run-time parameter checking in
611
+ AWS v4 (much better than in v3) and will generate an error when an illegal set
612
+ of parameters and/or values is given. Ruby/AWS will dynamically generate a
613
+ class for the type of error reported and raise an exception of that class.
527
614
 
528
615
  Using this approach, Ruby/AWS doesn't have to perform checks that Amazon will
529
- perform later anyway. This helps keep the code base leaner, the library
530
- faster, and reduces the chances of Ruby/AWS disallowing operations that will
531
- one day be allowed in a minor revision of AWS.
616
+ perform, anyway. This helps keep the code base leaner, the library faster, and
617
+ reduces the chance that Ruby/AWS will disallow an operation that becomes valid
618
+ following a minor revision of AWS.
532
619
 
533
620
 
534
621
  Documentation
@@ -539,14 +626,14 @@ command, executed from the directory created when you unpacked the archive:
539
626
 
540
627
  rdoc -SUx CVS lib
541
628
 
542
- The documentation on how to use this library is currently incomplete, but that
543
- is steadily being remedied.
629
+ The documentation on how to use this library is currently incomplete, but it
630
+ should be enough to get you started.
544
631
 
545
632
  You can also use the Ruby/AWS mailing-list:
546
633
 
547
634
  http://www.caliban.org/mailman/listinfo/ruby-aws
548
635
 
549
- to discuss all Ruby/AWS-related subjects and issues.
636
+ to discuss any Ruby/AWS-related subjects and issues.
550
637
 
551
638
 
552
639
  Examples
@@ -558,8 +645,8 @@ The ./examples subdirectory contains working examples of code.
558
645
  Licence
559
646
  -------
560
647
 
561
- This software is copyright (C) 2008 Ian Macdonald and distributed under the
562
- terms of the GNU GENERAL PUBLIC LICENSE, a copy of which is included.
648
+ This software is copyright (C) 2008-2009 Ian Macdonald and distributed under
649
+ the terms of the GNU GENERAL PUBLIC LICENSE, a copy of which is included.
563
650
 
564
651
  --
565
652
  Ian Macdonald