ruby-aaws 0.6.0 → 0.7.0
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 +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
|