ruby-aaws 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL +260 -0
- data/NEWS +116 -1
- data/README +13 -7
- data/README.rdoc +12 -10
- data/example/example1 +3 -3
- data/lib/amazon.rb +9 -7
- data/lib/amazon/aws.rb +212 -65
- data/lib/amazon/aws/search.rb +62 -16
- data/test/setup.rb +4 -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 +54 -6
- data/test/tc_list_lookup.rb +55 -0
- data/test/tc_list_search.rb +55 -0
- data/test/tc_multiple_operation.rb +201 -2
- 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_similarity_lookup.rb +59 -0
- data/test/tc_tag_lookup.rb +35 -0
- data/test/tc_transaction_lookup.rb +35 -0
- data/test/ts_aws.rb +16 -5
- metadata +29 -3
data/example/example1
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
#
|
3
|
-
# $Id: example1,v 1.
|
3
|
+
# $Id: example1,v 1.5 2009/06/02 01:09:51 ianmacd Exp $
|
4
4
|
|
5
5
|
require 'amazon/aws'
|
6
6
|
require 'amazon/aws/search'
|
@@ -44,7 +44,7 @@ response = request.search( is, rg, :ALL_PAGES ) do |page|
|
|
44
44
|
# end
|
45
45
|
# end
|
46
46
|
# end
|
47
|
-
|
47
|
+
printf( "Page %d had unique request ID %s.\n",
|
48
48
|
page_nr += 1,
|
49
49
|
page.item_search_response[0].operation_request[0].request_id )
|
50
50
|
printf( "Page %d contained %d result(s).\n",
|
@@ -56,7 +56,7 @@ end
|
|
56
56
|
#
|
57
57
|
nr_items = 0
|
58
58
|
response.each do |page|
|
59
|
-
|
59
|
+
page.item_search_response[0].items.each do |item_set|
|
60
60
|
nr_items += item_set.item.size
|
61
61
|
end
|
62
62
|
end
|
data/lib/amazon.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: amazon.rb,v 1.
|
1
|
+
# $Id: amazon.rb,v 1.29 2009/06/08 15:20:11 ianmacd Exp $
|
2
2
|
#
|
3
3
|
|
4
4
|
module Amazon
|
@@ -26,26 +26,28 @@ module Amazon
|
|
26
26
|
# Shamelessly plagiarised from Wakou Aoyama's cgi.rb, but then altered
|
27
27
|
# slightly to please AWS.
|
28
28
|
#
|
29
|
-
string.gsub( /([^a-zA-Z0-9_.~-]+)/
|
30
|
-
'%' + $1.unpack( 'H2' * $1.
|
29
|
+
string.gsub( /([^a-zA-Z0-9_.~-]+)/ ) do
|
30
|
+
'%' + $1.unpack( 'H2' * $1.bytesize ).join( '%' ).upcase
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
|
35
35
|
# Convert a string from CamelCase to ruby_case.
|
36
36
|
#
|
37
|
-
def Amazon.uncamelise(
|
37
|
+
def Amazon.uncamelise(string)
|
38
38
|
# Avoid modifying by reference.
|
39
39
|
#
|
40
|
-
|
40
|
+
string = string.dup
|
41
41
|
|
42
42
|
# Don't mess with string if all caps.
|
43
43
|
#
|
44
|
-
|
44
|
+
if string =~ /[a-z]/
|
45
|
+
string.gsub!( /(.+?)(([A-Z][a-z]|[A-Z]+$))/, "\\1_\\2" )
|
46
|
+
end
|
45
47
|
|
46
48
|
# Convert to lower case.
|
47
49
|
#
|
48
|
-
|
50
|
+
string.downcase
|
49
51
|
end
|
50
52
|
|
51
53
|
|
data/lib/amazon/aws.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: aws.rb,v 1.
|
1
|
+
# $Id: aws.rb,v 1.118 2009/06/15 23:51:53 ianmacd Exp $
|
2
2
|
#
|
3
3
|
#:include: ../../README.rdoc
|
4
4
|
|
@@ -8,12 +8,13 @@ module Amazon
|
|
8
8
|
|
9
9
|
require 'amazon'
|
10
10
|
require 'amazon/aws/cache'
|
11
|
+
require 'enumerator'
|
11
12
|
require 'iconv'
|
12
13
|
require 'rexml/document'
|
13
14
|
require 'uri'
|
14
15
|
|
15
16
|
NAME = '%s/%s' % [ Amazon::NAME, 'AWS' ]
|
16
|
-
VERSION = '0.
|
17
|
+
VERSION = '0.7.0'
|
17
18
|
USER_AGENT = '%s %s' % [ NAME, VERSION ]
|
18
19
|
|
19
20
|
# Default Associate tags to use per locale.
|
@@ -121,7 +122,10 @@ module Amazon
|
|
121
122
|
# If so, sign the request for authentication.
|
122
123
|
#
|
123
124
|
if request.config['secret_key_id']
|
124
|
-
request.sign
|
125
|
+
unless request.sign
|
126
|
+
Amazon.dprintf( 'Warning! Failed to sign request. No OpenSSL support for SHA256 digest.' )
|
127
|
+
end
|
128
|
+
|
125
129
|
url = ENDPOINT[request.locale].path + request.query
|
126
130
|
end
|
127
131
|
|
@@ -252,7 +256,7 @@ module Amazon
|
|
252
256
|
# dynamically defined by a separate process.
|
253
257
|
#
|
254
258
|
def AWSObject.yaml_load(io)
|
255
|
-
|
259
|
+
io.each do |line|
|
256
260
|
|
257
261
|
# File data is external, so it's deemed unsafe when $SAFE > 0, which
|
258
262
|
# is the case with mod_ruby, for example, where $SAFE == 1.
|
@@ -269,7 +273,7 @@ module Amazon
|
|
269
273
|
|
270
274
|
# Module#const_defined? takes 2 parameters in Ruby 1.9.
|
271
275
|
#
|
272
|
-
cl_name << false if
|
276
|
+
cl_name << false if RUBY_VERSION >= '1.9.0'
|
273
277
|
|
274
278
|
unless AWSObject.const_defined?( *cl_name )
|
275
279
|
AWSObject.const_set( m[1], Class.new( AWSObject ) )
|
@@ -299,6 +303,9 @@ module Amazon
|
|
299
303
|
iv = '@' + method.id2name
|
300
304
|
|
301
305
|
if instance_variables.include?( iv )
|
306
|
+
|
307
|
+
# Return the instance variable that matches the method called.
|
308
|
+
#
|
302
309
|
instance_variable_get( iv )
|
303
310
|
elsif instance_variables.include?( iv.to_sym )
|
304
311
|
|
@@ -306,6 +313,12 @@ module Amazon
|
|
306
313
|
# not String.
|
307
314
|
#
|
308
315
|
instance_variable_get( iv.to_sym )
|
316
|
+
elsif @__val__.respond_to?( method.id2name )
|
317
|
+
|
318
|
+
# If our value responds to the method in question, call the method
|
319
|
+
# on that.
|
320
|
+
#
|
321
|
+
@__val__.send( method.id2name )
|
309
322
|
else
|
310
323
|
nil
|
311
324
|
end
|
@@ -355,13 +368,8 @@ module Amazon
|
|
355
368
|
alias :to_str :to_s
|
356
369
|
|
357
370
|
|
358
|
-
def to_i # :nodoc:
|
359
|
-
@__val__.to_i
|
360
|
-
end
|
361
|
-
|
362
|
-
|
363
371
|
def ==(other) # :nodoc:
|
364
|
-
|
372
|
+
@__val__.to_s == other
|
365
373
|
end
|
366
374
|
|
367
375
|
|
@@ -456,7 +464,7 @@ module Amazon
|
|
456
464
|
|
457
465
|
# Module#const_defined? takes 2 parameters in Ruby 1.9.
|
458
466
|
#
|
459
|
-
cl_name << false if
|
467
|
+
cl_name << false if RUBY_VERSION >= '1.9.0'
|
460
468
|
|
461
469
|
# Create a class for the new element type unless it already exists.
|
462
470
|
#
|
@@ -503,12 +511,12 @@ module Amazon
|
|
503
511
|
#
|
504
512
|
def get(discount=nil)
|
505
513
|
if self.class.to_s =~ /Image$/ && @url
|
506
|
-
|
507
|
-
|
514
|
+
url = URI.parse( @url[0] )
|
515
|
+
url.path.sub!( /(\.\d\d\._)/, "\\1PE#{discount}" ) if discount
|
508
516
|
|
509
517
|
# FIXME: All HTTP in Ruby/AWS should go through the same method.
|
510
518
|
#
|
511
|
-
|
519
|
+
Net::HTTP.start( url.host, url.port ) do |http|
|
512
520
|
http.get( url.path )
|
513
521
|
end.body
|
514
522
|
|
@@ -589,28 +597,35 @@ module Amazon
|
|
589
597
|
OPERATIONS = %w[
|
590
598
|
BrowseNodeLookup CustomerContentLookup CustomerContentSearch
|
591
599
|
Help ItemLookup ItemSearch
|
592
|
-
ListLookup ListSearch
|
593
|
-
SellerListingSearch
|
594
|
-
TagLookup
|
595
|
-
VehiclePartSearch
|
600
|
+
ListLookup ListSearch MultipleOperation
|
601
|
+
SellerListingLookup SellerListingSearch SellerLookup
|
602
|
+
SimilarityLookup TagLookup TransactionLookup
|
603
|
+
VehiclePartLookup VehiclePartSearch VehicleSearch
|
596
604
|
|
597
605
|
CartAdd CartClear CartCreate
|
598
606
|
CartGet CartModify
|
599
607
|
]
|
600
608
|
|
601
609
|
attr_reader :kind
|
602
|
-
attr_accessor :params
|
610
|
+
attr_accessor :params, :response_group
|
603
611
|
|
604
612
|
def initialize(parameters)
|
605
613
|
|
606
614
|
op_kind = self.class.to_s.sub( /^.*::/, '' )
|
607
|
-
unless OPERATIONS.include?( op_kind )
|
615
|
+
unless OPERATIONS.include?( op_kind )
|
608
616
|
raise "Bad operation: #{op_kind}"
|
609
617
|
end
|
610
618
|
#raise 'Too many parameters' if parameters.size > 10
|
611
619
|
|
612
620
|
@kind = op_kind
|
613
621
|
@params = { 'Operation' => op_kind }.merge( parameters )
|
622
|
+
|
623
|
+
if ResponseGroup::DEFAULT.key?( op_kind )
|
624
|
+
@response_group =
|
625
|
+
ResponseGroup.new( ResponseGroup::DEFAULT[op_kind] )
|
626
|
+
else
|
627
|
+
@response_group = nil
|
628
|
+
end
|
614
629
|
end
|
615
630
|
|
616
631
|
|
@@ -625,10 +640,12 @@ module Amazon
|
|
625
640
|
#
|
626
641
|
# is = ItemSearch.new( 'Books', { 'Title' => 'ruby programming' } )
|
627
642
|
# is2 = ItemSearch.new( 'Music', { 'Artist' => 'stranglers' } )
|
628
|
-
#
|
643
|
+
# is.response_group = ResponseGroup.new( :Small )
|
644
|
+
# is2.response_group = ResponseGroup.new( :Tracks )
|
645
|
+
# is.batch( is2 )
|
629
646
|
#
|
630
|
-
#
|
631
|
-
#
|
647
|
+
# Please see MultipleOperation.new for implementation details that also
|
648
|
+
# apply to batched operations.
|
632
649
|
#
|
633
650
|
def batch(*operations)
|
634
651
|
|
@@ -650,6 +667,7 @@ module Amazon
|
|
650
667
|
# Apply batch syntax.
|
651
668
|
#
|
652
669
|
@params = batch_parameters( @params, op.params )
|
670
|
+
@response_group.params = batch_response_groups( op )
|
653
671
|
end
|
654
672
|
|
655
673
|
# Reinstate the Operation parameter.
|
@@ -665,28 +683,33 @@ module Amazon
|
|
665
683
|
@index ||= 1
|
666
684
|
|
667
685
|
unless b_params.empty?
|
668
|
-
op_str = self.class.to_s.sub(
|
686
|
+
op_str = @kind || self.class.to_s.sub( /^.*::/, '' )
|
669
687
|
|
670
688
|
# Fudge the operation string if we're dealing with a shopping cart.
|
671
689
|
#
|
672
690
|
op_str = 'Item' if op_str =~ /^Cart/
|
673
691
|
|
674
|
-
all_parameters =
|
692
|
+
all_parameters = []
|
675
693
|
|
676
694
|
# Shopping carts pass an empty hash in params, so we have to ditch
|
677
695
|
# params in such a case to prevent the batch index from being off by
|
678
696
|
# one.
|
679
697
|
#
|
680
698
|
all_parameters.concat( [ params ] ) unless params.empty?
|
699
|
+
all_parameters.concat( b_params )
|
681
700
|
|
682
701
|
params = {}
|
702
|
+
index = 0
|
703
|
+
|
704
|
+
all_parameters.each do |hash|
|
683
705
|
|
684
|
-
|
706
|
+
next if hash.empty?
|
685
707
|
|
686
708
|
# Don't batch an already batched hash.
|
687
709
|
#
|
688
|
-
if
|
689
|
-
params
|
710
|
+
if hash.to_a[0][0] =~ /^.+\..+\..+$/
|
711
|
+
params.merge!( hash )
|
712
|
+
@index += 1
|
690
713
|
next
|
691
714
|
end
|
692
715
|
|
@@ -694,6 +717,8 @@ module Amazon
|
|
694
717
|
shared_param = '%s.%d.%s' % [ op_str, @index + index, tag ]
|
695
718
|
params[shared_param] = val
|
696
719
|
end
|
720
|
+
|
721
|
+
index += 1
|
697
722
|
end
|
698
723
|
|
699
724
|
@index += b_params.size
|
@@ -706,40 +731,87 @@ module Amazon
|
|
706
731
|
end
|
707
732
|
|
708
733
|
|
734
|
+
# Convert response groups to batch format, e.g. ItemSearch.1.ResponseGroup.
|
735
|
+
#
|
736
|
+
def batch_response_groups(operation)
|
737
|
+
|
738
|
+
rg = {}
|
739
|
+
op_count = Hash.new( 1 )
|
740
|
+
|
741
|
+
[ self, operation ].each do |op|
|
742
|
+
rg_hash = op.response_group.params
|
743
|
+
|
744
|
+
if m = rg_hash.to_a[0][0].match( /^(.+)\..+\..+$/ )
|
745
|
+
# This hash is already in batch format.
|
746
|
+
#
|
747
|
+
rg.merge!( rg_hash )
|
748
|
+
|
749
|
+
# Keep a record of the highest index currently in use for each type
|
750
|
+
# of operation.
|
751
|
+
#
|
752
|
+
rg_hash.each do |key, val|
|
753
|
+
op_kind, index = key.match( /^(.+)\.(\d+)\..+$/ )[1, 2]
|
754
|
+
if index.to_i == op_count[op_kind]
|
755
|
+
op_count[op_kind] += 1
|
756
|
+
end
|
757
|
+
end
|
758
|
+
|
759
|
+
else
|
760
|
+
# Convert hash to batch format.
|
761
|
+
#
|
762
|
+
rg_hash.each_value do |val|
|
763
|
+
rg_str = '%s.%d.ResponseGroup' % [ op.kind, op_count[op.kind] ]
|
764
|
+
op_count[op.kind] += 1
|
765
|
+
rg[rg_str] = val
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
end
|
770
|
+
|
771
|
+
rg
|
772
|
+
end
|
773
|
+
|
774
|
+
|
709
775
|
# This class can be used to merge multiple operations into a single
|
710
776
|
# operation for greater efficiency.
|
711
777
|
#
|
712
778
|
class MultipleOperation < Operation
|
713
779
|
|
714
|
-
# This
|
715
|
-
#
|
716
|
-
#
|
717
|
-
#
|
780
|
+
# This allows you to take two Operation objects and combine them to form
|
781
|
+
# a single object, which can then be used to perform a single request to
|
782
|
+
# AWS. This allows for greater efficiency, reducing the number of
|
783
|
+
# requests sent to AWS.
|
718
784
|
#
|
719
|
-
# AWS currently imposes a limit of two
|
720
|
-
# operation.
|
785
|
+
# AWS currently imposes a limit of two operations when encapsulating
|
786
|
+
# operations in a multiple operation.
|
721
787
|
#
|
722
788
|
# <em>operation1</em> and <em>operation2</em> are both objects from a
|
723
789
|
# subclass of Operation, such as ItemSearch, ItemLookup, etc.
|
724
790
|
#
|
725
|
-
#
|
726
|
-
# of multiple operations:
|
791
|
+
# Please note the following implementation details:
|
727
792
|
#
|
728
|
-
# -
|
729
|
-
#
|
730
|
-
#
|
793
|
+
# - If you use the _response_group_ parameter of Search::Request#search
|
794
|
+
# to pass the list of response groups, it will apply to both
|
795
|
+
# operations.
|
796
|
+
#
|
797
|
+
# If you want to use a different response group set for each
|
798
|
+
# operation, you should assign the relevant groups to the
|
799
|
+
# @response_group attribute of each Operation object. You must do this
|
800
|
+
# *before* you instantiate the MultipleOperation.
|
731
801
|
#
|
732
802
|
# - One or both operations may have multiple results pages available,
|
733
803
|
# but only the first page is returned. If you need the subsequent
|
734
804
|
# pages, perform the operations separately, not as part of a
|
735
|
-
#
|
805
|
+
# multiple operation.
|
736
806
|
#
|
737
807
|
# Example:
|
738
808
|
#
|
739
809
|
# is = ItemSearch.new( 'Books', { 'Title' => 'Ruby' } )
|
740
810
|
# il = ItemLookup.new( 'ASIN', { 'ItemId' => 'B0013DZAYO',
|
741
811
|
# 'MerchantId' => 'Amazon' } )
|
742
|
-
#
|
812
|
+
# is.response_group = ResponseGroup.new( :Large )
|
813
|
+
# il.response_group = ResponseGroup.new( :Small )
|
814
|
+
# mo = MultipleOperation.new( is, il )
|
743
815
|
#
|
744
816
|
# As you can see, the operations that are combined as a
|
745
817
|
# MultipleOperation do not have to belong to the same class. In the
|
@@ -751,22 +823,14 @@ module Amazon
|
|
751
823
|
#
|
752
824
|
def initialize(operation1, operation2)
|
753
825
|
|
754
|
-
|
755
|
-
# is to protect me, not for user code.
|
756
|
-
#
|
757
|
-
operation1.freeze
|
758
|
-
operation2.freeze
|
759
|
-
|
760
|
-
op_kind = '%s,%s' % [ operation1.kind, operation2.kind ]
|
826
|
+
op_kind = [ operation1.kind, operation2.kind ].join( ',' )
|
761
827
|
|
762
828
|
# Duplicate Operation objects and remove their Operation parameter.
|
763
829
|
#
|
764
830
|
op1 = operation1.dup
|
765
|
-
op1.params = op1.params.dup
|
766
831
|
op1.params.delete( 'Operation' )
|
767
832
|
|
768
833
|
op2 = operation2.dup
|
769
|
-
op2.params = op2.params.dup
|
770
834
|
op2.params.delete( 'Operation' )
|
771
835
|
|
772
836
|
if op1.class == op2.class
|
@@ -787,6 +851,9 @@ module Amazon
|
|
787
851
|
params = { 'Operation' => op_kind }.merge( b_params )
|
788
852
|
super( params )
|
789
853
|
|
854
|
+
@response_group = ResponseGroup.new( [] )
|
855
|
+
@response_group.params.delete( 'ResponseGroup' )
|
856
|
+
@response_group.params = op1.batch_response_groups( op2 )
|
790
857
|
end
|
791
858
|
|
792
859
|
end
|
@@ -861,6 +928,7 @@ module Amazon
|
|
861
928
|
HealthPersonalCare
|
862
929
|
Hobbies
|
863
930
|
HomeGarden
|
931
|
+
HomeImprovement
|
864
932
|
Industrial
|
865
933
|
Jewelry
|
866
934
|
KindleStore
|
@@ -877,12 +945,14 @@ module Amazon
|
|
877
945
|
PCHardware
|
878
946
|
PetSupplies
|
879
947
|
Photo
|
880
|
-
|
948
|
+
Shoes
|
949
|
+
SilverMerchants
|
881
950
|
Software
|
882
951
|
SoftwareVideoGames
|
883
952
|
SportingGoods
|
884
953
|
Tools
|
885
954
|
Toys
|
955
|
+
UnboxVideo
|
886
956
|
VHS
|
887
957
|
Video
|
888
958
|
VideoGames
|
@@ -1098,7 +1168,7 @@ module Amazon
|
|
1098
1168
|
# <b>3P722DU4KUPCP</b> is retrieved from AWS.
|
1099
1169
|
#
|
1100
1170
|
def initialize(list_id, list_type, parameters={})
|
1101
|
-
|
1171
|
+
super( { 'ListId' => list_id,
|
1102
1172
|
'ListType' => list_type
|
1103
1173
|
}.merge( parameters ) )
|
1104
1174
|
end
|
@@ -1304,27 +1374,45 @@ module Amazon
|
|
1304
1374
|
end
|
1305
1375
|
|
1306
1376
|
# Response groups determine which data pertaining to the item(s) being
|
1307
|
-
# sought is returned. They
|
1308
|
-
#
|
1309
|
-
#
|
1310
|
-
#
|
1377
|
+
# sought is returned. They strongly influence the amount of data returned,
|
1378
|
+
# so you should always use the smallest response group(s) containing the
|
1379
|
+
# data of interest to you, to avoid masses of unnecessary data being
|
1380
|
+
# returned.
|
1311
1381
|
#
|
1312
1382
|
class ResponseGroup
|
1313
1383
|
|
1314
|
-
|
1384
|
+
# The default type of response group to use with each type of operation.
|
1385
|
+
#
|
1386
|
+
DEFAULT = { 'BrowseNodeLookup' => [ :BrowseNodeInfo, :TopSellers ],
|
1387
|
+
'CustomerContentLookup' => [ :CustomerInfo, :CustomerLists ],
|
1388
|
+
'CustomerContentSearch' => :CustomerInfo,
|
1389
|
+
'Help' => :Help,
|
1390
|
+
'ItemLookup' => :Large,
|
1391
|
+
'ItemSearch' => :Large,
|
1392
|
+
'ListLookup' => [ :ListInfo, :Small ],
|
1393
|
+
'ListSearch' => :ListInfo,
|
1394
|
+
'SellerListingLookup' => :SellerListing,
|
1395
|
+
'SellerListingSearch' => :SellerListing,
|
1396
|
+
'SellerLookup' => :Seller,
|
1397
|
+
'SimilarityLookup' => :Large,
|
1398
|
+
'TagLookup' => [ :Tags, :TagsSummary ],
|
1399
|
+
'TransactionLookup' => :TransactionDetails,
|
1400
|
+
'VehiclePartLookup' => :VehiclePartFit,
|
1401
|
+
'VehiclePartSearch' => :VehicleParts,
|
1402
|
+
'VehicleSearch' => :VehicleMakes
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
attr_reader :list
|
1406
|
+
attr_accessor :params
|
1315
1407
|
|
1316
1408
|
# Define a set of one or more response groups to be applied to items
|
1317
1409
|
# retrieved by an AWS operation.
|
1318
1410
|
#
|
1319
|
-
# If no response groups are given in _rg_ when instantiating an object,
|
1320
|
-
# *Small* will be used by default.
|
1321
|
-
#
|
1322
1411
|
# Example:
|
1323
1412
|
#
|
1324
1413
|
# rg = ResponseGroup.new( 'Medium', 'Offers', 'Reviews' )
|
1325
1414
|
#
|
1326
1415
|
def initialize(*rg)
|
1327
|
-
rg << 'Small' if rg.empty?
|
1328
1416
|
@list = rg
|
1329
1417
|
@params = { 'ResponseGroup' => @list.join( ',' ) }
|
1330
1418
|
end
|
@@ -1342,13 +1430,19 @@ module Amazon
|
|
1342
1430
|
class AWSError < AmazonError; end
|
1343
1431
|
|
1344
1432
|
def Error.exception(xml)
|
1345
|
-
|
1346
|
-
|
1433
|
+
err_class = xml.elements['Code'].text.sub( /^AWS.*\./, '' )
|
1434
|
+
err_msg = xml.elements['Message'].text
|
1347
1435
|
|
1348
1436
|
# Dynamically define a new exception class for this class of error,
|
1349
1437
|
# unless it already exists.
|
1350
1438
|
#
|
1351
|
-
|
1439
|
+
# Note that Ruby 1.9's Module.const_defined? needs a second parameter
|
1440
|
+
# of *false*, or it will also search AWSError's ancestors.
|
1441
|
+
#
|
1442
|
+
cd_params = [ err_class ]
|
1443
|
+
cd_params << false if RUBY_VERSION >= '1.9.0'
|
1444
|
+
|
1445
|
+
unless Amazon::AWS::Error.const_defined?( *cd_params )
|
1352
1446
|
Amazon::AWS::Error.const_set( err_class, Class.new( AWSError ) )
|
1353
1447
|
end
|
1354
1448
|
|
@@ -1359,6 +1453,59 @@ module Amazon
|
|
1359
1453
|
|
1360
1454
|
end
|
1361
1455
|
|
1456
|
+
|
1457
|
+
# Create a shorthand module method for each of the AWS operations. These
|
1458
|
+
# can be used to create less verbose code at the expense of flexibility.
|
1459
|
+
#
|
1460
|
+
# For example, we might normally write the following code:
|
1461
|
+
#
|
1462
|
+
# is = ItemSearch.new( 'Books', { 'Title' => 'Ruby' } )
|
1463
|
+
# rg = ResponseGroup.new( 'Large' )
|
1464
|
+
# req = Request.new
|
1465
|
+
# response = req.search( is, rg )
|
1466
|
+
#
|
1467
|
+
# but we could instead use ItemSearch's associated module method as
|
1468
|
+
# follows:
|
1469
|
+
#
|
1470
|
+
# response = Amazon::AWS.item_search( 'Books', { 'Title' => 'Ruby' } )
|
1471
|
+
#
|
1472
|
+
# Note that these equivalent module methods all attempt to use the *Large*
|
1473
|
+
# response group, which may or may not work. If an
|
1474
|
+
# Amazon::AWS::Error::InvalidResponseGroup is raised, we will scan the
|
1475
|
+
# text of the error message returned by AWS to try to glean a valid
|
1476
|
+
# response group and then retry the operation using that instead.
|
1477
|
+
|
1478
|
+
|
1479
|
+
# Ontain a list of all subclasses of the Operation class.
|
1480
|
+
#
|
1481
|
+
classes =
|
1482
|
+
ObjectSpace.enum_for( :each_object, class << Operation; self; end ).to_a
|
1483
|
+
|
1484
|
+
classes.each do |cl|
|
1485
|
+
# Convert class name to Ruby case, e.g. ItemSearch => item_search.
|
1486
|
+
#
|
1487
|
+
class_name = cl.to_s.sub( /^.+::/, '' )
|
1488
|
+
uncamelised_name = Amazon.uncamelise( class_name )
|
1489
|
+
|
1490
|
+
# Define the module method counterpart of each operation.
|
1491
|
+
#
|
1492
|
+
module_eval %Q(
|
1493
|
+
def AWS.#{uncamelised_name}(*params)
|
1494
|
+
# Instantiate an object of the desired operational class.
|
1495
|
+
#
|
1496
|
+
op = #{cl.to_s}.new( *params )
|
1497
|
+
|
1498
|
+
# Attempt a search for the given operation using its default
|
1499
|
+
# response group types.
|
1500
|
+
#
|
1501
|
+
results = Search::Request.new.search( op )
|
1502
|
+
yield results if block_given?
|
1503
|
+
return results
|
1504
|
+
|
1505
|
+
end
|
1506
|
+
)
|
1507
|
+
end
|
1508
|
+
|
1362
1509
|
end
|
1363
1510
|
|
1364
1511
|
end
|