kernow-ruby-aaws 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # $Id: seller_lookup1,v 1.1 2008/04/27 10:10:07 ianmacd Exp $
4
+
5
+ require 'amazon/aws/search'
6
+
7
+ include Amazon::AWS
8
+ include Amazon::AWS::Search
9
+
10
+ def display_properties(root, indent=0)
11
+ if root[0].respond_to? :properties
12
+ printf( 'Property %s =', root[0] )
13
+ root[0].properties.each do |pr|
14
+ display_properties( pr, indent + 2 )
15
+ end
16
+ else
17
+ printf( "Property %s = %s.\n", root, root.to_h[root] )
18
+ end
19
+ end
20
+
21
+ sl = SellerLookup.new( 'A3QFR0K2KCB7EG' )
22
+ sl_rg = ResponseGroup.new( 'Seller' )
23
+
24
+ req = Request.new
25
+ req.locale = 'us'
26
+
27
+ resp = req.search( sl, sl_rg ).seller_lookup_response
28
+
29
+ seller = resp.sellers.seller
30
+
31
+ seller.properties.each do |pr|
32
+ if seller[0][pr][0].properties.empty?
33
+ printf( "%s = %s.\n", pr, seller[0][pr] )
34
+ else
35
+ seller[0][pr][0].properties.each do |nest1|
36
+ if seller[0][pr][0][nest1][0].properties.empty?
37
+ printf( "%s = %s.\n", nest1, seller[0][pr][0][nest1][0] )
38
+ else
39
+ seller[0][pr][0][nest1][0].properties.each do |nest2|
40
+ printf( "%s = %s.\n", nest2, seller[0][pr][0][nest1][0][nest2] )
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # $Id: shopping_cart1,v 1.2 2008/06/06 13:31:40 ianmacd Exp $
4
+
5
+ require 'amazon/aws/search'
6
+ require 'amazon/aws/shoppingcart'
7
+
8
+ include Amazon::AWS
9
+ #include Amazon::AWS::Search
10
+ include Amazon::AWS::ShoppingCart
11
+
12
+ cart = Cart.new
13
+ cart.locale = 'uk'
14
+
15
+ cart.cart_create( :ASIN, 'B00151HZA6', 3, false,
16
+ { 'B000WC4AH0' => 2 ,
17
+ 'B000PY32OM' => 8 } )
18
+
19
+ puts cart.cart_id
20
+ puts cart.hmac
21
+ puts cart.purchase_url
22
+ puts
23
+
24
+ cart.cart_add( :ASIN, 'B0014C2BL4', 1,
25
+ { 'B00006BCKL' => 5 },
26
+ { 'B000VVE2UW' => 4 } )
27
+ cart.cart_add( :ASIN, 'B0013F2M52', 3 )
28
+ cart.cart_add( :ASIN, 'B000HCPSR6', 5 )
29
+ cart.cart_modify( :ASIN, 'B00151HZA6', 2, true,
30
+ { 'B0013F2M52' => 1 },
31
+ { 'B000HCPSR6' => 3 } )
32
+
33
+ puts 'Cart contents:'
34
+ cart.each do |it|
35
+ puts "ASIN: %s, item Id: %-14s, quantity: %d" %
36
+ [ it.asin, it.cart_item_id, it.quantity ]
37
+ end
38
+ puts
39
+
40
+ puts cart.items
41
+
42
+ cart.cart_clear
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # $Id: similarity_lookup1,v 1.1 2008/04/27 06:03:54 ianmacd Exp $
4
+
5
+ require 'amazon/aws'
6
+ require 'amazon/aws/search'
7
+
8
+ include Amazon::AWS
9
+ include Amazon::AWS::Search
10
+
11
+ # Example of a batch operation, using the ASIN as the shared ID.
12
+ #
13
+ sl = SimilarityLookup.new( [ 'B000AE4QEC', 'B000051WBE' ] )
14
+
15
+ # You can have multiple response groups.
16
+ #
17
+ rg = ResponseGroup.new( 'Medium', 'Offers', 'Reviews' )
18
+
19
+ req = Request.new
20
+ req.locale = 'uk'
21
+
22
+ resp = req.search( sl, rg )
23
+ item_sets = resp.similarity_lookup_response[0].items
24
+
25
+ item_sets.each do |item_set|
26
+ item_set.item.each do |item|
27
+ attribs = item.item_attributes[0]
28
+ puts attribs.label
29
+ if attribs.list_price
30
+ puts attribs.title, attribs.list_price[0].formatted_price
31
+ end
32
+
33
+ # Availability has become a cumbersome thing to retrieve in AWSv4.
34
+ #
35
+ puts 'Availability: %s' %
36
+ [ item.offers[0].offer[0].offer_listing[0].availability ]
37
+ puts 'Average rating: %s' % [ item.customer_reviews[0].average_rating ]
38
+ puts 'Reviewed by %s customers.' %
39
+ [ item.customer_reviews[0].total_reviews ]
40
+
41
+ puts 'Customers said:'
42
+ item.customer_reviews[0].review.each do |review|
43
+ puts ' %s (%s votes)' % [ review.summary, review.total_votes ]
44
+ end
45
+
46
+ puts
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # $Id: tag_lookup1,v 1.1 2008/04/27 19:46:43 ianmacd Exp $
4
+
5
+ require 'amazon/aws'
6
+ require 'amazon/aws/search'
7
+
8
+ include Amazon::AWS
9
+ include Amazon::AWS::Search
10
+
11
+ tag_str = 'Awful'
12
+ tl = TagLookup.new( tag_str )
13
+
14
+ # You can have multiple response groups.
15
+ #
16
+ rg = ResponseGroup.new( 'Tags', 'TagsSummary' )
17
+
18
+ req = Request.new
19
+ req.locale = 'us'
20
+
21
+ resp = req.search( tl, rg )
22
+ tag = resp.tag_lookup_response.tags.tag
23
+
24
+ printf( "Tag name '%s' has %d distinct items.\n", tag_str, tag.distinct_items )
25
+ printf( "Tag has %d distinct items.\n", tag.distinct_users )
26
+ printf( "Tag has %d total usages.\n", tag.total_usages )
27
+ printf( "Tagged for the first time in entity %s on %s\nby %s..\n",
28
+ tag.first_tagging.entity_id,
29
+ tag.first_tagging.time,
30
+ tag.first_tagging.user_id )
31
+ printf( "Tagged for the last time in entity %s on %s\nby %s..\n",
32
+ tag.last_tagging.entity_id,
33
+ tag.last_tagging.time,
34
+ tag.last_tagging.user_id )
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/ruby -w
2
+ #
3
+ # $Id: transaction_lookup1,v 1.1 2008/04/27 21:24:21 ianmacd Exp $
4
+
5
+ require 'amazon/aws'
6
+ require 'amazon/aws/search'
7
+
8
+ include Amazon::AWS
9
+ include Amazon::AWS::Search
10
+
11
+ tl = TransactionLookup.new( '103-5663398-5028241' )
12
+
13
+ rg = ResponseGroup.new( 'TransactionDetails' )
14
+
15
+ req = Request.new
16
+ req.locale = 'us'
17
+
18
+ resp = req.search( tl, rg )
19
+ trans = resp.transaction_lookup_response.transactions.transaction
20
+
21
+ printf( "Transaction date was %s.\n", trans.transaction_date )
22
+ printf( "It was in the amount of %s and the seller was %s.\n",
23
+ trans.totals.total.formatted_price, trans.seller_name )
24
+ printf( "The shipping charge was %s and the package was sent by %s.\n",
25
+ trans.totals.shipping_charge.formatted_price,
26
+ trans.shipments.shipment.delivery_method )
@@ -0,0 +1,141 @@
1
+ # $Id: cache.rb,v 1.8 2008/06/10 06:33:46 ianmacd Exp $
2
+ #
3
+
4
+ module Amazon
5
+
6
+ module AWS
7
+
8
+ # This class provides a simple results caching system for operations
9
+ # performed by AWS.
10
+ #
11
+ # To use it, set _cache_ to *true* in either <tt>/etc/amazonrc</tt> or
12
+ # <tt>~/.amazonrc</tt>.
13
+ #
14
+ # By default, the cache directory used is <tt>/tmp/amazon</tt>, but this
15
+ # can be changed by defining _cache_dir_ in either <tt>/etc/amazonrc</tt>
16
+ # or <tt>~/.amazonrc</tt>.
17
+ #
18
+ # When a cache is used, Ruby/AWS will check the cache directory for a
19
+ # recent copy of a response to the exact operation that you are
20
+ # performing. If found, the cached response will be returned instead of
21
+ # the request being forwarded to the AWS servers for processing. If no
22
+ # (recent) copy is found, the request will be forwarded to the AWS servers
23
+ # as usual. Recency is defined here as less than 24 hours old.
24
+ #
25
+ class Cache
26
+
27
+ require 'fileutils'
28
+
29
+ begin
30
+ require 'md5'
31
+ rescue LoadError
32
+ # Ruby 1.9 has moved MD5.
33
+ #
34
+ require 'digest/md5'
35
+ end
36
+
37
+ # Exception class for bad cache paths.
38
+ #
39
+ class PathError < StandardError; end
40
+
41
+ # Length of one day in seconds
42
+ #
43
+ ONE_DAY = 86400 # :nodoc:
44
+
45
+ # Age in days below which to consider cache files valid.
46
+ #
47
+ MAX_AGE = 1.0
48
+
49
+ # Default cache location.
50
+ #
51
+ DEFAULT_CACHE_DIR = '/tmp/amazon'
52
+
53
+ attr_reader :path
54
+
55
+ def initialize(path=DEFAULT_CACHE_DIR)
56
+ path ||= DEFAULT_CACHE_DIR
57
+
58
+ ::FileUtils::mkdir_p( path ) unless File.exists? path
59
+
60
+ unless File.directory? path
61
+ raise PathError, "cache path #{path} is not a directory"
62
+ end
63
+
64
+ unless File.readable? path
65
+ raise PathError, "cache path #{path} is not readable"
66
+ end
67
+
68
+ unless File.writable? path
69
+ raise PathError, "cache path #{path} is not writable"
70
+ end
71
+
72
+ @path = path
73
+ end
74
+
75
+
76
+ # Determine whether or not the the response to a given URL is cached.
77
+ # Returns *true* or *false*.
78
+ #
79
+ def cached?(url)
80
+ digest = Digest::MD5.hexdigest( url )
81
+
82
+ cache_files = Dir.glob( File.join( @path, '*' ) ).map do |d|
83
+ File.basename( d )
84
+ end
85
+
86
+ return cache_files.include?( digest ) &&
87
+ ( Time.now - File.mtime( File.join( @path, digest ) ) ) /
88
+ ONE_DAY <= MAX_AGE
89
+ end
90
+
91
+
92
+ # Retrieve the cached response associated with _url_.
93
+ #
94
+ def fetch(url)
95
+ digest = Digest::MD5.hexdigest( url )
96
+ cache_file = File.join( @path, digest )
97
+
98
+ return nil unless File.exist? cache_file
99
+
100
+ Amazon.dprintf( 'Fetching %s from cache...', digest )
101
+ File.open( File.join( cache_file ) ).readlines.to_s
102
+ end
103
+
104
+
105
+ # Cache the data from _contents_ and associate it with _url_.
106
+ #
107
+ def store(url, contents)
108
+ digest = Digest::MD5.hexdigest( url )
109
+ cache_file = File.join( @path, digest )
110
+
111
+ Amazon.dprintf( 'Caching %s...', digest )
112
+ File.open( cache_file, 'w' ) { |f| f.puts contents }
113
+ end
114
+
115
+
116
+ # This method flushes all files from the cache directory specified
117
+ # in the object's <i>@path</i> variable.
118
+ #
119
+ def flush_all
120
+ FileUtils.rm Dir.glob( File.join( @path, '*' ) )
121
+ end
122
+
123
+
124
+ # This method flushes expired files from the cache directory specified
125
+ # in the object's <i>@path</i> variable.
126
+ #
127
+ def flush_expired
128
+ now = Time.now
129
+
130
+ expired_files = Dir.glob( File.join( @path, '*' ) ).find_all do |f|
131
+ ( now - File.mtime( f ) ) / ONE_DAY > MAX_AGE
132
+ end
133
+
134
+ FileUtils.rm expired_files
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,334 @@
1
+ # $Id: search.rb,v 1.26 2008/09/21 22:17:32 ianmacd Exp $
2
+ #
3
+
4
+ module Amazon
5
+
6
+ module AWS
7
+
8
+ require 'amazon/aws'
9
+ require 'net/http'
10
+ require 'rexml/document'
11
+
12
+ # Load this library with:
13
+ #
14
+ # require 'amazon/aws/search'
15
+ #
16
+ module Search
17
+
18
+ class Request
19
+
20
+ include REXML
21
+
22
+ # Exception class for bad access key ID.
23
+ #
24
+ class AccessKeyIdError < Amazon::AWS::Error::AWSError; end
25
+
26
+ # Exception class for bad locales.
27
+ #
28
+ class LocaleError < Amazon::AWS::Error::AWSError; end
29
+
30
+ attr_reader :conn, :locale, :user_agent
31
+ attr_writer :cache
32
+
33
+ # This method is used to generate an AWS search request object.
34
+ #
35
+ # _key_id_ is your AWS {access key
36
+ # ID}[https://aws-portal.amazon.com/gp/aws/developer/registration/index.html],
37
+ # _associate_ is your
38
+ # Associates[http://docs.amazonwebservices.com/AWSECommerceService/2008-04-07/GSG/BecominganAssociate.html]
39
+ # tag (if any), _locale_ is the locale in which you which to work
40
+ # (*us* for amazon.com[http://www.amazon.com/], *uk* for
41
+ # amazon.co.uk[http://www.amazon.co.uk], etc.), _cache_ is whether or
42
+ # not you wish to utilise a response cache, and _user_agent_ is the
43
+ # client name to pass when performing calls to AWS. By default,
44
+ # _user_agent_ will be set to a string identifying the Ruby/AWS
45
+ # library and its version number.
46
+ #
47
+ # _locale_ and _cache_ can also be set later, if you wish to change
48
+ # the current behaviour.
49
+ #
50
+ # Example:
51
+ #
52
+ # req = Request.new( '0Y44V8FAFNM119CX4TR2', 'calibanorg-20' )
53
+ #
54
+ def initialize(key_id=nil, associate=nil, locale=nil, cache=nil,
55
+ cache_dir=nil, user_agent=USER_AGENT)
56
+
57
+ @config ||= Amazon::Config.new
58
+
59
+ def_locale = locale
60
+ locale = 'us' unless locale
61
+ locale.downcase!
62
+
63
+ key_id ||= @config['key_id']
64
+ cache = @config['cache'] if cache.nil?
65
+ cache_dir ||= @config['cache_dir']
66
+
67
+ # Take locale from config file if no locale was passed to method.
68
+ #
69
+ if @config.key?( 'locale' ) && ! def_locale
70
+ locale = @config['locale']
71
+ end
72
+ validate_locale( locale )
73
+
74
+ if key_id.nil?
75
+ raise AccessKeyIdError, 'key_id may not be nil'
76
+ end
77
+
78
+ @key_id = key_id
79
+ @tag = associate || @config['associate'] || DEF_ASSOC[locale]
80
+ @user_agent = user_agent
81
+ @cache = unless cache == 'false' || cache == false
82
+ Amazon::AWS::Cache.new( cache_dir )
83
+ else
84
+ nil
85
+ end
86
+ self.locale = locale
87
+ end
88
+
89
+
90
+ # Assign a new locale. If the locale we're coming from is using the
91
+ # default Associate ID for that locale, then we use the new locale's
92
+ # default ID, too.
93
+ #
94
+ def locale=(l) # :nodoc:
95
+ old_locale = @locale ||= nil
96
+ @locale = validate_locale( l )
97
+
98
+ # Use the new locale's default ID if the ID currently in use is the
99
+ # current locale's default ID.
100
+ #
101
+ if @tag == Amazon::AWS::DEF_ASSOC[old_locale]
102
+ @tag = Amazon::AWS::DEF_ASSOC[@locale]
103
+ end
104
+
105
+ # We must now set up a new HTTP connection to the correct server for
106
+ # this locale, unless the same server is used for both.
107
+ #
108
+ unless Amazon::AWS::ENDPOINT[@locale] ==
109
+ Amazon::AWS::ENDPOINT[old_locale]
110
+ #connect( @locale )
111
+ @conn = nil
112
+ end
113
+ end
114
+
115
+
116
+ # If @cache has simply been assigned *true* at some point in time,
117
+ # assign a proper cache object to it when it is referenced. Otherwise,
118
+ # just return its value.
119
+ #
120
+ def cache # :nodoc:
121
+ if @cache == true
122
+ @cache = Amazon::AWS::Cache.new( @config['cache_dir'] )
123
+ else
124
+ @cache
125
+ end
126
+ end
127
+
128
+
129
+ # Verify the validity of a locale string. _l_ is the locale string.
130
+ #
131
+ def validate_locale(l)
132
+ unless Amazon::AWS::ENDPOINT.has_key? l
133
+ raise LocaleError, "invalid locale: #{l}"
134
+ end
135
+ l
136
+ end
137
+ private :validate_locale
138
+
139
+
140
+ # Return an HTTP connection for the current _locale_.
141
+ #
142
+ def connect(locale)
143
+ if ENV.key? 'http_proxy'
144
+ uri = URI.parse( ENV['http_proxy'] )
145
+ proxy_user = proxy_pass = nil
146
+ proxy_user, proxy_pass = uri.userinfo.split( /:/ ) if uri.userinfo
147
+ @conn = Net::HTTP::Proxy( uri.host, uri.port, proxy_user,
148
+ proxy_pass ).start(
149
+ Amazon::AWS::ENDPOINT[locale].host )
150
+ else
151
+ @conn = Net::HTTP::start( Amazon::AWS::ENDPOINT[locale].host )
152
+ end
153
+ end
154
+ private :connect
155
+
156
+
157
+ # Reconnect to the server if our connection has been lost (due to a
158
+ # time-out, etc.).
159
+ #
160
+ def reconnect # :nodoc:
161
+ connect( self.locale )
162
+ self
163
+ end
164
+
165
+
166
+ # This method checks for errors in an XML response returned by AWS.
167
+ # _xml_ is the XML node below which to search.
168
+ #
169
+ def error_check(xml)
170
+ if xml = xml.elements['Errors/Error']
171
+ raise Amazon::AWS::Error.exception( xml )
172
+ end
173
+ end
174
+ private :error_check
175
+
176
+
177
+ # Perform a search of the AWS database. _operation_ is one of the
178
+ # objects subclassed from _Operation_, such as _ItemSearch_,
179
+ # _ItemLookup_, etc. It may also be a _MultipleOperation_ object.
180
+ #
181
+ # _response_group_ will apply to all both operations contained in
182
+ # _operation_, if _operation_ is a _MultipleOperation_ object.
183
+ #
184
+ # _nr_pages_ is the number of results pages to return. It defaults to
185
+ # <b>1</b>. If a higher number is given, pages 1 to _nr_pages_ will be
186
+ # returned. If the special value <b>:ALL_PAGES</b> is given, all
187
+ # results pages will be returned.
188
+ #
189
+ # The maximum page number that can be returned for each type of
190
+ # operation is documented in the AWS Developer's Guide:
191
+ #
192
+ # http://docs.amazonwebservices.com/AWSECommerceService/2008-08-19/DG/index.html?CHAP_MakingRequestsandUnderstandingResponses.html#PagingThroughResults
193
+ #
194
+ # Note that _ItemLookup_ operations can use three separate pagination
195
+ # parameters. Ruby/AWS, however, uses _OfferPage_ for the purposes of
196
+ # returning multiple pages.
197
+ #
198
+ # If operation is of class _MultipleOperation_, the operations
199
+ # combined within will return only the first page, regardless of
200
+ # whether a higher number of pages is requested.
201
+ #
202
+ def search(operation, response_group, nr_pages=1)
203
+ q_params = Amazon::AWS::SERVICE.
204
+ merge( { 'AWSAccessKeyId' => @key_id,
205
+ 'AssociateTag' => @tag } ).
206
+ merge( operation.params ).
207
+ merge( response_group.params )
208
+
209
+ query = Amazon::AWS.assemble_query( q_params )
210
+ page = Amazon::AWS.get_page( self, query )
211
+ doc = Document.new( page )
212
+
213
+ # Some errors occur at the very top level of the XML. For example,
214
+ # when no Operation parameter is given. This should not be possible
215
+ # with user code, but occurred during debugging of this library.
216
+ #
217
+ error_check( doc )
218
+
219
+ # Fundamental errors happen at the OperationRequest level. For
220
+ # example, if an invalid AWSAccessKeyId is used.
221
+ #
222
+ error_check( doc.elements['*/OperationRequest'] )
223
+
224
+ # Check for parameter and value errors deeper down, inside Request.
225
+ #
226
+ if operation.kind == 'MultipleOperation'
227
+
228
+ # Everything is a level deeper, because of the
229
+ # <MultiOperationResponse> container.
230
+ #
231
+ # Check for errors in the first operation.
232
+ #
233
+ error_check( doc.elements['*/*/*/Request'] )
234
+
235
+ # Check for errors in the second operation.
236
+ #
237
+ error_check( doc.elements['*/*[3]/*/Request'] )
238
+
239
+ # If second operation is batched, check for errors in its 2nd set
240
+ # of results.
241
+ #
242
+ if batched = doc.elements['*/*[3]/*[2]/Request']
243
+ error_check( batched )
244
+ end
245
+ else
246
+ error_check( doc.elements['*/*/Request'] )
247
+
248
+ # If operation is batched, check for errors in its 2nd set of
249
+ # results.
250
+ #
251
+ if batched = doc.elements['*/*[3]/Request']
252
+ error_check( batched )
253
+ end
254
+ end
255
+
256
+ # FIXME: This doesn't work if a MultipleOperation was used, because
257
+ # <TotalPages> will be nested one level deeper. It's therefore
258
+ # currently only possible to return the first page of results
259
+ # for operations combined in a MultipleOperation.
260
+ #
261
+ if doc.elements['*/*[2]/TotalPages']
262
+ total_pages = doc.elements['*/*[2]/TotalPages'].text.to_i
263
+ else
264
+ total_pages = 1
265
+ end
266
+
267
+ # Create a root AWS object and walk the XML response tree.
268
+ #
269
+ aws = AWS::AWSObject.new( operation )
270
+ aws.walk( doc )
271
+ result = aws
272
+
273
+ # If only one page has been requested or only one page is available,
274
+ # we can stop here. First yield to the block, if given.
275
+ #
276
+ if nr_pages == 1 || ( tp = total_pages ) == 1
277
+ yield result if block_given?
278
+ return result
279
+ end
280
+
281
+ # Limit the number of pages to the maximum number available.
282
+ #
283
+ nr_pages = tp.to_i if nr_pages == :ALL_PAGES || nr_pages > tp.to_i
284
+
285
+ if PAGINATION.key? operation.kind
286
+ page_parameter = PAGINATION[operation.kind]['parameter']
287
+ max_pages = PAGINATION[operation.kind]['max_page']
288
+ else
289
+ page_parameter = 'ItemPage'
290
+ max_pages = 400
291
+ end
292
+
293
+ # Iterate over pages 2 and higher, but go no higher than MAX_PAGES.
294
+ #
295
+ 2.upto( nr_pages < max_pages ? nr_pages : max_pages ) do |page_nr|
296
+ query = Amazon::AWS.assemble_query(
297
+ q_params.merge( { page_parameter => page_nr } ) )
298
+ page = Amazon::AWS.get_page( self, query )
299
+ doc = Document.new( page )
300
+
301
+ # Check for errors.
302
+ #
303
+ error_check( doc.elements['*/OperationRequest'] )
304
+ error_check( doc.elements['*/*/Request'] )
305
+
306
+ # Create a new AWS object and walk the XML response tree.
307
+ #
308
+ aws = AWS::AWSObject.new
309
+ aws.walk( doc )
310
+
311
+ # When dealing with multiple pages, we return not just an
312
+ # AWSObject, but an array of them.
313
+ #
314
+ result = [ result ] unless result.is_a? Array
315
+
316
+ # Append the new object to the array.
317
+ #
318
+ result << aws
319
+ end
320
+
321
+ # Yield each object to the block, if given.
322
+ #
323
+ result.each { |r| yield r } if block_given?
324
+
325
+ result
326
+ end
327
+
328
+ end
329
+
330
+ end
331
+
332
+ end
333
+
334
+ end