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/INSTALL +7 -6
- data/NEWS +600 -272
- data/README +250 -163
- data/README.rdoc +145 -129
- data/Rakefile +13 -32
- data/VERSION +1 -0
- data/example/batch_operation +27 -0
- data/example/example1 +3 -3
- data/example/item_lookup1 +5 -4
- data/example/item_lookup2 +5 -4
- data/example/multiple_operation1 +4 -3
- data/example/vehicle_search +22 -0
- data/lib/amazon.rb +34 -16
- data/lib/amazon/aws.rb +496 -161
- data/lib/amazon/aws/search.rb +148 -28
- data/ruby-aaws.gemspec +117 -0
- data/test/setup.rb +5 -2
- data/test/tc_aws.rb +2 -2
- data/test/tc_browse_node_lookup.rb +62 -0
- data/test/tc_customer_content_lookup.rb +64 -0
- data/test/tc_help.rb +60 -0
- data/test/tc_item_lookup.rb +60 -0
- data/test/tc_item_search.rb +88 -3
- data/test/tc_list_lookup.rb +55 -0
- data/test/tc_list_search.rb +55 -0
- data/test/tc_multiple_operation.rb +211 -4
- data/test/tc_seller_listing_lookup.rb +58 -0
- data/test/tc_seller_listing_search.rb +70 -0
- data/test/tc_seller_lookup.rb +54 -0
- data/test/tc_shopping_cart.rb +9 -9
- data/test/tc_similarity_lookup.rb +59 -0
- data/test/tc_tag_lookup.rb +35 -0
- data/test/tc_transaction_lookup.rb +35 -0
- data/test/tc_vehicle_operations.rb +106 -0
- data/test/ts_aws.rb +16 -4
- metadata +85 -49
- data/ruby-aws.gemspec +0 -57
- data/ruby-aws.spec +0 -177
data/README
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
$Id: README,v 1.
|
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
|
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
|
29
|
-
version of the Amazon API
|
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
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
Since Amazon
|
42
|
-
AWS is now just one of many. It is therefore no longer appropriate
|
43
|
-
this library by a name so general as Ruby/Amazon, because it
|
44
|
-
|
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
|
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
|
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
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
72
|
-
|
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
|
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/
|
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
|
101
|
+
Ruby/AWS is currently beta software. Amongst other things, this means:
|
88
102
|
|
89
|
-
- You will
|
90
|
-
|
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
|
93
|
-
|
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.
|
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
|
-
|
99
|
-
|
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
|
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
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
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.
|
138
|
-
shrink or disappear
|
139
|
-
|
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
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
172
|
-
|
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
|
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
|
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
|
268
|
+
.amazonrc, you may define the $AMAZONRCFILE environment variable.
|
198
269
|
|
199
|
-
Once you have your configuration file, you can get started
|
270
|
+
Once you have your configuration file, you can get started writing your code.
|
200
271
|
|
201
|
-
Here's
|
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
|
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 (
|
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
|
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
|
-
-
|
347
|
-
|
348
|
-
|
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
|
352
|
-
know the ASIN of the first item found, we can refer to this as
|
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>
|
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>
|
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>
|
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)
|
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
|
-
|
380
|
-
|
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
|
-
|
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>
|
388
|
-
object will therefore always
|
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
|
391
|
-
successfully
|
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.
|
399
|
-
array
|
400
|
-
|
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
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
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
|
415
|
-
|
416
|
-
multiple <Item>
|
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
|
420
|
-
|
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
|
423
|
-
array, as it can't be known which element the method invocation
|
424
|
-
|
425
|
-
that an array contains only a single element when
|
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
|
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,
|
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,
|
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
|
438
|
-
precisely which data will be returned by a given search.
|
439
|
-
non-existent attributes
|
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
|
454
|
-
ever yield an item with a FooBar
|
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
|
466
|
-
For example, specifying the parameter 'Author' with
|
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
|
472
|
-
|
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,
|
475
|
-
TransactionLookup operations, for example, don't
|
476
|
-
|
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
|
485
|
-
number of operations, parameters
|
486
|
-
v4 API, this strict approach
|
487
|
-
|
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
|
570
|
+
pass sensible parameters and values for the locale in which you're working.
|
571
|
+
The context is now your responsibility.
|
491
572
|
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
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
|
-
|
499
|
-
|
500
|
-
|
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
|
503
|
-
|
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,
|
509
|
-
SearchIndex in the 'us' locale,
|
510
|
-
|
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
|
513
|
-
developer documentation (and closely follow the release notes of each
|
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
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
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
|
530
|
-
|
531
|
-
|
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
|
543
|
-
|
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
|
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
|
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
|