aws-sdk 1.1.4 → 1.2.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/lib/aws.rb +2 -0
- data/lib/aws/api_config/ELB-2011-08-15.yml +380 -0
- data/lib/aws/api_config/SNS-2010-03-31.yml +2 -2
- data/lib/aws/api_config/SimpleEmailService-2010-12-01.yml +5 -5
- data/lib/aws/core.rb +18 -3
- data/lib/aws/core/client_logging.rb +5 -6
- data/lib/aws/core/collection.rb +241 -0
- data/lib/aws/core/collection/batchable.rb +133 -0
- data/lib/aws/core/collection/limitable.rb +92 -0
- data/lib/aws/core/collection/simple.rb +89 -0
- data/lib/aws/core/configuration.rb +23 -0
- data/lib/aws/core/option_grammar.rb +2 -0
- data/lib/aws/core/page_result.rb +73 -0
- data/lib/aws/ec2/security_group.rb +154 -89
- data/lib/aws/ec2/security_group/egress_ip_permission_collection.rb +1 -2
- data/lib/aws/ec2/security_group/{ip_permission_collection.rb → ingress_ip_permission_collection.rb} +4 -1
- data/lib/aws/ec2/security_group/ip_permission.rb +23 -45
- data/lib/aws/elb.rb +65 -0
- data/lib/aws/elb/availability_zone_collection.rb +138 -0
- data/lib/aws/elb/backend_server_policy_collection.rb +150 -0
- data/lib/aws/elb/client.rb +35 -0
- data/lib/aws/elb/client/xml.rb +33 -0
- data/lib/aws/elb/config.rb +18 -0
- data/lib/aws/elb/errors.rb +30 -0
- data/lib/aws/elb/instance_collection.rb +174 -0
- data/lib/aws/elb/listener.rb +189 -0
- data/lib/aws/elb/listener_collection.rb +119 -0
- data/lib/aws/elb/listener_opts.rb +45 -0
- data/lib/aws/elb/listener_spec.rb +14 -0
- data/lib/aws/elb/load_balancer.rb +255 -0
- data/lib/aws/elb/load_balancer_collection.rb +113 -0
- data/lib/aws/elb/load_balancer_policy.rb +93 -0
- data/lib/aws/elb/load_balancer_policy_collection.rb +208 -0
- data/lib/aws/elb/request.rb +23 -0
- data/lib/aws/iam/collection.rb +24 -26
- data/lib/aws/iam/group_user_collection.rb +21 -28
- data/lib/aws/iam/server_certificate_collection.rb +1 -37
- data/lib/aws/record.rb +1 -1
- data/lib/aws/record/base.rb +14 -1
- data/lib/aws/record/finder_methods.rb +4 -1
- data/lib/aws/record/validations.rb +73 -32
- data/lib/aws/{core/api_config_transform.rb → record/validators/method.rb} +9 -12
- data/lib/aws/s3/bucket_collection.rb +6 -4
- data/lib/aws/s3/client.rb +37 -6
- data/lib/aws/s3/config.rb +3 -1
- data/lib/aws/s3/prefixed_collection.rb +1 -2
- data/lib/aws/s3/presigned_post.rb +37 -4
- data/lib/aws/s3/s3_object.rb +93 -1
- data/lib/aws/simple_db/domain.rb +8 -0
- data/lib/aws/simple_db/item.rb +15 -0
- data/lib/aws/simple_db/item_collection.rb +255 -201
- data/lib/aws/simple_db/item_data.rb +1 -1
- data/lib/aws/simple_email_service/client.rb +0 -1
- data/lib/aws/sns/client.rb +0 -1
- metadata +107 -55
- data/lib/aws/core/collections.rb +0 -229
- data/lib/aws/simple_email_service/client/options.rb +0 -21
- data/lib/aws/sns/client/options.rb +0 -21
data/lib/aws/s3/config.rb
CHANGED
@@ -79,6 +79,7 @@ module AWS
|
|
79
79
|
:content_encoding,
|
80
80
|
:expires_header,
|
81
81
|
:acl,
|
82
|
+
:server_side_encryption,
|
82
83
|
:success_action_redirect,
|
83
84
|
:success_action_status]
|
84
85
|
|
@@ -153,6 +154,15 @@ module AWS
|
|
153
154
|
# * +:bucket_owner_read+
|
154
155
|
# * +:bucket_owner_full_control+
|
155
156
|
#
|
157
|
+
# @option options [Symbol] :server_side_encryption (nil) If this
|
158
|
+
# option is set, the object will be stored using server side
|
159
|
+
# encryption. The only valid value is +:aes256+, which
|
160
|
+
# specifies that the object should be stored using the AES
|
161
|
+
# encryption algorithm with 256 bit keys. By default, this
|
162
|
+
# option uses the value of the +:s3_server_side_encryption+
|
163
|
+
# option in the current configuration; for more information,
|
164
|
+
# see {AWS.config}.
|
165
|
+
#
|
156
166
|
# @option opts [String] :success_action_redirect The URL to
|
157
167
|
# which the client is redirected upon successful upload.
|
158
168
|
#
|
@@ -197,6 +207,12 @@ module AWS
|
|
197
207
|
@expires = opts[:expires]
|
198
208
|
|
199
209
|
super
|
210
|
+
|
211
|
+
@fields[:server_side_encryption] =
|
212
|
+
config.s3_server_side_encryption unless
|
213
|
+
@fields.key?(:server_side_encryption)
|
214
|
+
@fields.delete(:server_side_encryption) if
|
215
|
+
@fields[:server_side_encryption].nil?
|
200
216
|
end
|
201
217
|
|
202
218
|
# @return [Boolean] True if {#url} generates an HTTPS url.
|
@@ -415,13 +431,10 @@ module AWS
|
|
415
431
|
fields = (SPECIAL_FIELDS &
|
416
432
|
@fields.keys).inject({}) do |fields, option_name|
|
417
433
|
fields[field_name(option_name)] =
|
418
|
-
|
434
|
+
field_value(option_name)
|
419
435
|
fields
|
420
436
|
end
|
421
437
|
|
422
|
-
fields["acl"] = fields["acl"].tr("_", "-") if
|
423
|
-
fields["acl"]
|
424
|
-
|
425
438
|
@metadata.each do |key, value|
|
426
439
|
fields["x-amz-meta-#{key}"] = value.to_s
|
427
440
|
end
|
@@ -435,6 +448,8 @@ module AWS
|
|
435
448
|
case option_name
|
436
449
|
when :expires_header
|
437
450
|
"Expires"
|
451
|
+
when :server_side_encryption
|
452
|
+
"x-amz-server-side-encryption"
|
438
453
|
when :acl, :success_action_redirect, :success_action_status
|
439
454
|
option_name.to_s
|
440
455
|
else
|
@@ -446,6 +461,24 @@ module AWS
|
|
446
461
|
end
|
447
462
|
end
|
448
463
|
|
464
|
+
# @private
|
465
|
+
private
|
466
|
+
def field_value(option_name)
|
467
|
+
case option_name
|
468
|
+
when :acl
|
469
|
+
@fields[:acl].to_s.tr("_", "-")
|
470
|
+
when :server_side_encryption
|
471
|
+
value = @fields[:server_side_encryption]
|
472
|
+
if value.kind_of?(Symbol)
|
473
|
+
value.to_s.upcase
|
474
|
+
else
|
475
|
+
value.to_s
|
476
|
+
end
|
477
|
+
else
|
478
|
+
@fields[option_name].to_s
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
449
482
|
# @private
|
450
483
|
private
|
451
484
|
def generate_conditions
|
data/lib/aws/s3/s3_object.rb
CHANGED
@@ -82,12 +82,14 @@ module AWS
|
|
82
82
|
# * content_length (integer, number of bytes)
|
83
83
|
# * content_type (as sent to S3 when uploading the object)
|
84
84
|
# * etag (typically the object's MD5)
|
85
|
+
# * server_side_encryption (the algorithm used to encrypt the
|
86
|
+
# object on the server side, e.g. +:aes256+)
|
85
87
|
#
|
86
88
|
# @param [Hash] options
|
87
89
|
# @option options [String] :version_id Which version of this object
|
88
90
|
# to make a HEAD request against.
|
89
91
|
# @return A head object response with metatadata,
|
90
|
-
# content_length, content_type and
|
92
|
+
# content_length, content_type, etag and server_side_encryption.
|
91
93
|
def head options = {}
|
92
94
|
client.head_object(options.merge(
|
93
95
|
:bucket_name => bucket.name, :key => key))
|
@@ -124,6 +126,19 @@ module AWS
|
|
124
126
|
head.content_type
|
125
127
|
end
|
126
128
|
|
129
|
+
# @return [Symbol, nil] Returns the algorithm used to encrypt
|
130
|
+
# the object on the server side, or +nil+ if SSE was not used
|
131
|
+
# when storing the object.
|
132
|
+
def server_side_encryption
|
133
|
+
head.server_side_encryption
|
134
|
+
end
|
135
|
+
|
136
|
+
# @return [true, false] Returns true if the object was stored
|
137
|
+
# using server side encryption.
|
138
|
+
def server_side_encryption?
|
139
|
+
!server_side_encryption.nil?
|
140
|
+
end
|
141
|
+
|
127
142
|
# Deletes the object from its S3 bucket.
|
128
143
|
#
|
129
144
|
# @param [Hash] options
|
@@ -258,6 +273,15 @@ module AWS
|
|
258
273
|
# @option options :content_type A standard MIME type
|
259
274
|
# describing the format of the object data.
|
260
275
|
#
|
276
|
+
# @option options [Symbol] :server_side_encryption (nil) If this
|
277
|
+
# option is set, the object will be stored using server side
|
278
|
+
# encryption. The only valid value is +:aes256+, which
|
279
|
+
# specifies that the object should be stored using the AES
|
280
|
+
# encryption algorithm with 256 bit keys. By default, this
|
281
|
+
# option uses the value of the +:s3_server_side_encryption+
|
282
|
+
# option in the current configuration; for more information,
|
283
|
+
# see {AWS.config}.
|
284
|
+
#
|
261
285
|
# @return [S3Object, ObjectVersion] If the bucket has versioning
|
262
286
|
# enabled, returns the {ObjectVersion} representing the
|
263
287
|
# version that was uploaded. If versioning is disabled,
|
@@ -267,6 +291,8 @@ module AWS
|
|
267
291
|
(data_options, put_options) =
|
268
292
|
compute_put_options(options_or_data, options)
|
269
293
|
|
294
|
+
add_configured_write_options(put_options)
|
295
|
+
|
270
296
|
if use_multipart?(data_options, put_options)
|
271
297
|
put_options.delete(:multipart_threshold)
|
272
298
|
multipart_upload(put_options) do |upload|
|
@@ -363,11 +389,24 @@ module AWS
|
|
363
389
|
# @option options :content_type A standard MIME type
|
364
390
|
# describing the format of the object data.
|
365
391
|
#
|
392
|
+
# @option options [Symbol] :server_side_encryption (nil) If this
|
393
|
+
# option is set, the object will be stored using server side
|
394
|
+
# encryption. The only valid value is +:aes256+, which
|
395
|
+
# specifies that the object should be stored using the AES
|
396
|
+
# encryption algorithm with 256 bit keys. By default, this
|
397
|
+
# option uses the value of the +:s3_server_side_encryption+
|
398
|
+
# option in the current configuration; for more information,
|
399
|
+
# see {AWS.config}.
|
400
|
+
#
|
366
401
|
# @return [S3Object, ObjectVersion] If the bucket has versioning
|
367
402
|
# enabled, returns the {ObjectVersion} representing the
|
368
403
|
# version that was uploaded. If versioning is disabled,
|
369
404
|
# returns self.
|
370
405
|
def multipart_upload(options = {})
|
406
|
+
|
407
|
+
options = options.dup
|
408
|
+
add_configured_write_options(options)
|
409
|
+
|
371
410
|
upload = multipart_uploads.create(options)
|
372
411
|
|
373
412
|
if block_given?
|
@@ -399,6 +438,12 @@ module AWS
|
|
399
438
|
# and upload it again. You can also change the storage class and
|
400
439
|
# metadata of the object when copying.
|
401
440
|
#
|
441
|
+
# @note This operation does not copy the ACL, storage class
|
442
|
+
# (standard vs. reduced redundancy) or server side encryption
|
443
|
+
# setting from the source object. If you don't specify any of
|
444
|
+
# these options when copying, the object will have the default
|
445
|
+
# values as described below.
|
446
|
+
#
|
402
447
|
# @param [Mixed] source
|
403
448
|
#
|
404
449
|
# @param [Hash] options
|
@@ -430,6 +475,15 @@ module AWS
|
|
430
475
|
# * +:bucket_owner_read+
|
431
476
|
# * +:bucket_owner_full_control+
|
432
477
|
#
|
478
|
+
# @option options [Symbol] :server_side_encryption (nil) If this
|
479
|
+
# option is set, the object will be stored using server side
|
480
|
+
# encryption. The only valid value is +:aes256+, which
|
481
|
+
# specifies that the object should be stored using the AES
|
482
|
+
# encryption algorithm with 256 bit keys. By default, this
|
483
|
+
# option uses the value of the +:s3_server_side_encryption+
|
484
|
+
# option in the current configuration; for more information,
|
485
|
+
# see {AWS.config}.
|
486
|
+
#
|
433
487
|
# @return [nil]
|
434
488
|
def copy_from source, options = {}
|
435
489
|
|
@@ -458,6 +512,10 @@ module AWS
|
|
458
512
|
|
459
513
|
copy_opts[:acl] = options[:acl] if options[:acl]
|
460
514
|
copy_opts[:version_id] = options[:version_id] if options[:version_id]
|
515
|
+
copy_opts[:server_side_encryption] =
|
516
|
+
options[:server_side_encryption] if
|
517
|
+
options.key?(:server_side_encryption)
|
518
|
+
add_configured_write_options(copy_opts)
|
461
519
|
|
462
520
|
if options[:reduced_redundancy]
|
463
521
|
copy_opts[:storage_class] = 'REDUCED_REDUNDANCY'
|
@@ -477,6 +535,12 @@ module AWS
|
|
477
535
|
# and upload it again. You can also change the storage class and
|
478
536
|
# metadata of the object when copying.
|
479
537
|
#
|
538
|
+
# @note This operation does not copy the ACL, storage class
|
539
|
+
# (standard vs. reduced redundancy) or server side encryption
|
540
|
+
# setting from this object to the new object. If you don't
|
541
|
+
# specify any of these options when copying, the new object
|
542
|
+
# will have the default values as described below.
|
543
|
+
#
|
480
544
|
# @param [S3Object,String] target An S3Object, or a string key of
|
481
545
|
# and object to copy to.
|
482
546
|
#
|
@@ -497,6 +561,25 @@ module AWS
|
|
497
561
|
# the object is stored with reduced redundancy in S3 for a
|
498
562
|
# lower cost.
|
499
563
|
#
|
564
|
+
# @option options [Symbol] :acl (private) A canned access
|
565
|
+
# control policy. Valid values are:
|
566
|
+
#
|
567
|
+
# * +:private+
|
568
|
+
# * +:public_read+
|
569
|
+
# * +:public_read_write+
|
570
|
+
# * +:authenticated_read+
|
571
|
+
# * +:bucket_owner_read+
|
572
|
+
# * +:bucket_owner_full_control+
|
573
|
+
#
|
574
|
+
# @option options [Symbol] :server_side_encryption (nil) If this
|
575
|
+
# option is set, the object will be stored using server side
|
576
|
+
# encryption. The only valid value is +:aes256+, which
|
577
|
+
# specifies that the object should be stored using the AES
|
578
|
+
# encryption algorithm with 256 bit keys. By default, this
|
579
|
+
# option uses the value of the +:s3_server_side_encryption+
|
580
|
+
# option in the current configuration; for more information,
|
581
|
+
# see {AWS.config}.
|
582
|
+
#
|
500
583
|
# @return (see #copy_from)
|
501
584
|
def copy_to target, options = {}
|
502
585
|
|
@@ -825,6 +908,15 @@ module AWS
|
|
825
908
|
end
|
826
909
|
end
|
827
910
|
|
911
|
+
private
|
912
|
+
def add_configured_write_options(options)
|
913
|
+
options[:server_side_encryption] =
|
914
|
+
config.s3_server_side_encryption unless
|
915
|
+
options.key?(:server_side_encryption)
|
916
|
+
options.delete(:server_side_encryption) if
|
917
|
+
options[:server_side_encryption] == nil
|
918
|
+
end
|
919
|
+
|
828
920
|
# @private
|
829
921
|
private
|
830
922
|
def use_multipart?(data_options, options)
|
data/lib/aws/simple_db/domain.rb
CHANGED
@@ -100,6 +100,14 @@ module AWS
|
|
100
100
|
ItemCollection.new(self)
|
101
101
|
end
|
102
102
|
|
103
|
+
# @return [Boolean] Returns true if the domains are the same.
|
104
|
+
def == other
|
105
|
+
other.is_a?(Domain) and
|
106
|
+
other.name == name and
|
107
|
+
other.config.simple_db_endpoint == config.simple_db_endpoint
|
108
|
+
end
|
109
|
+
alias_method :eql?, :==
|
110
|
+
|
103
111
|
# An irb-friendly string representation of this object.
|
104
112
|
#
|
105
113
|
# @return [String]
|
data/lib/aws/simple_db/item.rb
CHANGED
@@ -49,6 +49,13 @@ module AWS
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# Deletes the item and all of its attributes from SimpleDB.
|
52
|
+
# @param [Hash] options
|
53
|
+
# @option options [Hash] :if Pass a hash with a single key (attribute
|
54
|
+
# name) and a single value (the attribute value). This causes the
|
55
|
+
# delete to become conditional.
|
56
|
+
# @option options [String,Symbol] :unless Pass an attribute name. This
|
57
|
+
# causes the delete to become conditional on that attribute not
|
58
|
+
# existing.
|
52
59
|
# @return [nil]
|
53
60
|
def delete options = {}
|
54
61
|
delete_opts = {}
|
@@ -72,6 +79,14 @@ module AWS
|
|
72
79
|
ItemData.new(:name => name, :domain => domain, :response_object => r)
|
73
80
|
end
|
74
81
|
|
82
|
+
def == other
|
83
|
+
other.is_a?(Item) and
|
84
|
+
other.domain == domain and
|
85
|
+
other.name == name
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method :eql?, :==
|
89
|
+
|
75
90
|
end
|
76
91
|
|
77
92
|
end
|
@@ -17,10 +17,27 @@ module AWS
|
|
17
17
|
# Represents a collection of items in a SimpleDB domain.
|
18
18
|
class ItemCollection
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
# Identifies quoted regions in the string, giving access to
|
21
|
+
# the regions before and after each quoted region, for example:
|
22
|
+
# "? ? `foo?``bar?` ? 'foo?' ?".scan(OUTSIDE_QUOTES_REGEX)
|
23
|
+
# # => [["? ? ", "`foo?``bar?`", " ? "], ["", "'foo?'", " ?"]]
|
24
|
+
# @private
|
25
|
+
OUTSIDE_QUOTES_REGEX = Regexp.compile(
|
26
|
+
'([^\'"`]*)(`(?:[^`]*(?:``))*[^`]*`|' +
|
27
|
+
'\'(?:[^\']*(?:\'\'))*[^\']*\'|' +
|
28
|
+
'"(?:[^"]*(?:""))*[^"]*")([^\'`"]*)'
|
29
|
+
)
|
30
|
+
|
22
31
|
include ConsistentReadOption
|
23
32
|
|
33
|
+
include Core::Collection::Limitable
|
34
|
+
|
35
|
+
# @return [Domain] The domain the items belong to.
|
36
|
+
attr_reader :domain
|
37
|
+
|
38
|
+
# @private
|
39
|
+
attr_reader :output_list
|
40
|
+
|
24
41
|
# @private
|
25
42
|
attr_reader :conditions
|
26
43
|
|
@@ -31,17 +48,14 @@ module AWS
|
|
31
48
|
# @return [ItemCollection]
|
32
49
|
def initialize domain, options = {}
|
33
50
|
@domain = domain
|
34
|
-
@
|
35
|
-
@conditions
|
36
|
-
@sort_instructions = options[:sort_instructions]
|
51
|
+
@output_list = options[:output_list] || 'itemName()'
|
52
|
+
@conditions = options[:conditions] || []
|
53
|
+
@sort_instructions = options[:sort_instructions]
|
37
54
|
@not_null_attribute = options[:not_null_attribute]
|
38
|
-
@limit = options[:limit]
|
55
|
+
@limit = options[:limit]
|
39
56
|
super
|
40
57
|
end
|
41
58
|
|
42
|
-
# @return [Domain] The domain the items belong to.
|
43
|
-
attr_reader :domain
|
44
|
-
|
45
59
|
# Creates a new item in SimpleDB with the given attributes:
|
46
60
|
#
|
47
61
|
# domain.items.create('shirt', {
|
@@ -78,132 +92,85 @@ module AWS
|
|
78
92
|
Item.new(domain, item_name.to_s)
|
79
93
|
end
|
80
94
|
|
81
|
-
# Yields to the block once for each item in the
|
95
|
+
# Yields to the block once for each item in the collection.
|
96
|
+
# This method can yield two type of objects:
|
82
97
|
#
|
83
|
-
#
|
98
|
+
# * AWS::SimpleDB::Item objects (only the item name is populated)
|
99
|
+
# * AWS::SimpleDB::ItemData objects (some or all attributes populated)
|
84
100
|
#
|
101
|
+
# The defualt mode of an ItemCollection is to yield Item objects with
|
102
|
+
# no populated attributes.
|
103
|
+
#
|
104
|
+
# # only receives item names from SimpleDB
|
85
105
|
# domain.items.each do |item|
|
86
106
|
# puts item.name
|
107
|
+
# puts item.class.name # => AWS::SimpleDB::Item
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# You can switch a collection into yielded {ItemData} objects by
|
111
|
+
# specifying what attributes to request:
|
112
|
+
#
|
113
|
+
# domain.items.select(:all).each do |item_data|
|
114
|
+
# puts item_data.class.name # => AWS::SimpleDB::ItemData
|
115
|
+
# puts item_data.attributes # => { 'attr-name' => 'attr-value', ... }
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# You can also pass the standard scope options to #each as well:
|
119
|
+
#
|
120
|
+
# # output the item names of the 10 most expesive items
|
121
|
+
# domain.items.each(:order => [:price, :desc], :limit => 10).each do |item|
|
122
|
+
# puts item.name
|
87
123
|
# end
|
88
124
|
#
|
89
125
|
# @yield [item] Yields once for every item in the {#domain}.
|
90
|
-
# @yieldparam [Item] item
|
91
|
-
# @param options (see #select)
|
92
|
-
# @option options (see #select)
|
93
|
-
# @option options [Symbol or Array] :select Causes this method
|
94
|
-
# to behave like {#select} and yield {ItemData} instead of
|
95
|
-
# {Item} instances.
|
96
|
-
# @option options :batch_size Specifies a maximum number of records
|
97
|
-
# to fetch from SimpleDB in a single request. SimpleDB may return
|
98
|
-
# fewer items than :batch_size per request, but never more.
|
99
|
-
# @return [nil]
|
100
|
-
def each options = {}, &block
|
101
|
-
|
102
|
-
handle_query_options(options) do |c, opts|
|
103
|
-
return c.each(opts, &block)
|
104
|
-
end
|
105
|
-
|
106
|
-
if attributes = options.delete(:select)
|
107
|
-
return select(attributes, options, &block)
|
108
|
-
end
|
109
|
-
|
110
|
-
perform_select(options) do |response|
|
111
|
-
response.items.each do |item|
|
112
|
-
yield(self[item.name])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
# Retrieves data from each item in the domain.
|
119
126
|
#
|
120
|
-
#
|
127
|
+
# @yieldparam [Item,ItemData] item If the item collection has been
|
128
|
+
# scoped by chaining +#select+ or by passing the +:select+ option
|
129
|
+
# then {ItemData} objects (that contain a hash of attrbiutes) are
|
130
|
+
# yielded. If no list of attributes has been provided, then#
|
131
|
+
# {Item} objects (with no populated data) are yielded.
|
121
132
|
#
|
122
|
-
#
|
123
|
-
# to retrieve the attributes of each of the top 100 items in order of
|
124
|
-
# descending popularity as an array of hashes, you could do:
|
133
|
+
# @param options [Hash]
|
125
134
|
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
# end
|
135
|
+
# @option options [Boolean] :consistent_read (false) Causes this
|
136
|
+
# method to yield the most current data in the domain.
|
129
137
|
#
|
130
|
-
#
|
131
|
-
#
|
138
|
+
# @option options [Mixed] :select If select is provided, then each
|
139
|
+
# will yield {ItemData} objects instead of empty {Item}.
|
140
|
+
# The +:select+ option may be:
|
132
141
|
#
|
133
|
-
#
|
134
|
-
# items.select(:color) {|data| colors += data.attributes["color"] }
|
142
|
+
# * +:all+ - Specifies that all attributes should requested.
|
135
143
|
#
|
136
|
-
#
|
137
|
-
#
|
144
|
+
# * A single or array of attribute names (as strings or symbols).
|
145
|
+
# This causes the named attribute(s) to be requested.
|
138
146
|
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
# :order => [:popularity, :desc],
|
142
|
-
# :limit => 100) do |data|
|
143
|
-
# puts "Data for #{data.name}: #{data.attributes.inspect}"
|
144
|
-
# end
|
147
|
+
# @option options :where Restricts the item collection using
|
148
|
+
# {#where} before querying (see {#where}).
|
145
149
|
#
|
146
|
-
# @
|
147
|
-
#
|
148
|
-
# The attributes to retrieve. This can be:
|
150
|
+
# @option options :order Changes the order in which the items
|
151
|
+
# will be yielded (see {#order}).
|
149
152
|
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
# * an array of Symbols or Strings to retrieve multiple attributes.
|
153
|
+
# @option options :limit [Integer] The maximum number of
|
154
|
+
# items to fetch from SimpleDB.
|
153
155
|
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
# cannot use this method to select the number of items; use
|
159
|
-
# {#count} instead.
|
156
|
+
# @option options :batch_size Specifies a maximum number of records
|
157
|
+
# to fetch from SimpleDB in a single request. SimpleDB may return
|
158
|
+
# fewer items than :batch_size per request, but never more.
|
159
|
+
# Generally you should not need to specify this option.
|
160
160
|
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
|
168
|
-
# @option options :limit [Integer] The maximum number of
|
169
|
-
# items to fetch from SimpleDB. More than one request may be
|
170
|
-
# required to satisfy the limit.
|
171
|
-
# @option options :batch_size Specifies a maximum number of records
|
172
|
-
# to fetch from SimpleDB in a single request. SimpleDB may return
|
173
|
-
# fewer items than :batch_size per request, but never more.
|
174
|
-
# @return If no block is given, an enumerator is returned. If a block
|
175
|
-
# was passed then nil is returned.
|
176
|
-
def select *attributes, &block
|
177
|
-
|
178
|
-
options = attributes.last.is_a?(Hash) ? attributes.pop : {}
|
179
|
-
|
180
|
-
args = attributes + [options]
|
181
|
-
|
182
|
-
handle_query_options(*args) do |c, *clean_args|
|
183
|
-
return c.select(*clean_args, &block)
|
184
|
-
end
|
185
|
-
|
186
|
-
unless block_given?
|
187
|
-
return Enumerator.new(self, :select, *args)
|
188
|
-
end
|
189
|
-
|
190
|
-
if attributes.empty?
|
191
|
-
output_list = '*'
|
192
|
-
#elsif attributes == ['*']
|
193
|
-
# output_list = '*'
|
194
|
-
else
|
195
|
-
output_list = [attributes].flatten.collect do |attr|
|
196
|
-
coerce_attribute(attr)
|
197
|
-
end.join(', ')
|
198
|
-
end
|
161
|
+
# @return [String,nil] Returns a next token that can be used with
|
162
|
+
# the exact same SimpleDB select expression to get more results.
|
163
|
+
# A next token is returned ONLY if there was a limit on the
|
164
|
+
# expression, otherwise all items will be enumerated and
|
165
|
+
# nil is returned.
|
166
|
+
#
|
167
|
+
def each options = {}, &block
|
199
168
|
|
200
|
-
|
201
|
-
|
202
|
-
yield(ItemData.new(:domain => domain, :response_object => item))
|
203
|
-
end
|
169
|
+
handle_query_options(options) do |collection, opts|
|
170
|
+
return collection.each(opts, &block)
|
204
171
|
end
|
205
172
|
|
206
|
-
|
173
|
+
super
|
207
174
|
|
208
175
|
end
|
209
176
|
|
@@ -211,31 +178,32 @@ module AWS
|
|
211
178
|
#
|
212
179
|
# domain.items.count
|
213
180
|
#
|
214
|
-
# You can
|
215
|
-
# the domain, or you can use it with {#where} to count a subset
|
216
|
-
# of items. For example, to count the items where the "color"
|
217
|
-
# attribute is "red":
|
181
|
+
# You can specify what items to count with {#where}:
|
218
182
|
#
|
219
|
-
# domain.items.where(
|
183
|
+
# domain.items.where(:color => "red").count
|
220
184
|
#
|
221
|
-
# You can also limit the number of items
|
222
|
-
# {#limit} method. For example, to count the number of items up
|
223
|
-
# to 500:
|
185
|
+
# You can also limit the number of items to count:
|
224
186
|
#
|
187
|
+
# # count up to 500 items and then stop
|
225
188
|
# domain.items.limit(500).count
|
226
189
|
#
|
227
190
|
# @param [Hash] options Options for counting items.
|
228
191
|
#
|
229
192
|
# @option options [Boolean] :consistent_read (false) Causes this
|
230
|
-
# method to yield the most current data in the domain
|
193
|
+
# method to yield the most current data in the domain when +true+.
|
194
|
+
#
|
231
195
|
# @option options :where Restricts the item collection using
|
232
196
|
# {#where} before querying.
|
197
|
+
#
|
233
198
|
# @option options :limit [Integer] The maximum number of
|
234
|
-
# items to
|
235
|
-
#
|
199
|
+
# items to count in SimpleDB.
|
200
|
+
#
|
201
|
+
# @return [Integer] The number of items counted.
|
202
|
+
#
|
236
203
|
def count options = {}, &block
|
237
|
-
|
238
|
-
|
204
|
+
|
205
|
+
handle_query_options(options) do |collection, opts|
|
206
|
+
return collection.count(opts, &block)
|
239
207
|
end
|
240
208
|
|
241
209
|
options = options.merge(:output_list => "count(*)")
|
@@ -243,30 +211,107 @@ module AWS
|
|
243
211
|
count = 0
|
244
212
|
next_token = nil
|
245
213
|
|
246
|
-
|
247
|
-
response = select_request(options, next_token)
|
214
|
+
begin
|
248
215
|
|
249
|
-
|
250
|
-
|
216
|
+
response = select_request(options, next_token)
|
217
|
+
|
218
|
+
if
|
219
|
+
domain_item = response.items.first and
|
220
|
+
count_attribute = domain_item.attributes.first
|
221
|
+
then
|
251
222
|
count += count_attribute.value.to_i
|
252
223
|
end
|
253
224
|
|
254
|
-
next_token = response.next_token
|
255
|
-
break unless next_token
|
225
|
+
break unless next_token = response.next_token
|
256
226
|
|
257
|
-
end
|
227
|
+
end while limit.nil? || count < limit
|
258
228
|
|
259
229
|
count
|
230
|
+
|
260
231
|
end
|
261
232
|
alias_method :size, :count
|
262
233
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
234
|
+
# # @return [PageResult] Returns an array-based object with results.
|
235
|
+
# # Results are either {Item} or {ItemData} objects depending on
|
236
|
+
# # the selection mode (item names only or with attributes).
|
237
|
+
# #
|
238
|
+
# def page options = {}
|
239
|
+
#
|
240
|
+
# handle_query_options(options) do |collection, opts|
|
241
|
+
# return collection.page(opts)
|
242
|
+
# end
|
243
|
+
#
|
244
|
+
# super(options)
|
245
|
+
#
|
246
|
+
# end
|
247
|
+
|
248
|
+
# Specifies a list of attributes select from SimpleDB.
|
249
|
+
#
|
250
|
+
# domain.items.select('size', 'color').each do |item_data|
|
251
|
+
# puts item_data.attributes # => { 'size' => ..., :color => ... }
|
252
|
+
# end
|
253
|
+
#
|
254
|
+
# You can select all attributes by passing +:all+ or '*':
|
255
|
+
#
|
256
|
+
# domain.items.select('*').each {|item_data| ... }
|
257
|
+
#
|
258
|
+
# domain.items.select(:all).each {|item_data| ... }
|
259
|
+
#
|
260
|
+
# Calling #select causes #each to yield {ItemData} objects
|
261
|
+
# with #attribute hashes, instead of {Item} objects with
|
262
|
+
# an item name.
|
263
|
+
#
|
264
|
+
# @param *attributes [Symbol, String, or Array] The attributes to
|
265
|
+
# retrieve. This can be:
|
266
|
+
#
|
267
|
+
# * +:all+ or '*' to request all attributes for each item
|
268
|
+
#
|
269
|
+
# * A list or array of attribute names as strinsg or symbols
|
270
|
+
#
|
271
|
+
# Attribute names may contain any characters that are valid
|
272
|
+
# in a SimpleDB attribute name; this method will handle
|
273
|
+
# escaping them for inclusion in the query. Note that you
|
274
|
+
# cannot use this method to select the number of items; use
|
275
|
+
# {#count} instead.
|
276
|
+
#
|
277
|
+
# @return [ItemCollection] Returns a new item collection with the
|
278
|
+
# specified list of attributes to select.
|
279
|
+
#
|
280
|
+
def select *attributes, &block
|
281
|
+
|
282
|
+
# Before select was morphed into a chainable method, it accepted
|
283
|
+
# a hash of options (e.g. :where, :order, :limit) that no longer
|
284
|
+
# make sense, but to maintain backwards compatability we still
|
285
|
+
# consume those.
|
286
|
+
#
|
287
|
+
# TODO : it would be a good idea to add a deprecation warning for
|
288
|
+
# passing options to #select
|
289
|
+
#
|
290
|
+
handle_query_options(*attributes) do |collection, *args|
|
291
|
+
return collection.select(*args, &block)
|
292
|
+
end
|
293
|
+
|
294
|
+
options = attributes.last.is_a?(Hash) ? attributes.pop : {}
|
295
|
+
|
296
|
+
output_list = case attributes.flatten
|
297
|
+
when [] then '*'
|
298
|
+
when ['*'] then '*'
|
299
|
+
when [:all] then '*'
|
300
|
+
else attributes.flatten.map{|attr| coerce_attribute(attr) }.join(', ')
|
301
|
+
end
|
302
|
+
|
303
|
+
collection = collection_with(:output_list => output_list)
|
304
|
+
|
305
|
+
if block_given?
|
306
|
+
# previously select accepted a block and it would enumerate items
|
307
|
+
# this is for backwards compatability
|
308
|
+
collection.each(options, &block)
|
309
|
+
nil
|
310
|
+
else
|
311
|
+
collection
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
270
315
|
|
271
316
|
# Returns an item collection defined by the given conditions
|
272
317
|
# in addition to any conditions defined on this collection.
|
@@ -333,7 +378,8 @@ module AWS
|
|
333
378
|
#
|
334
379
|
# @return [ItemCollection] Returns a new item collection with the
|
335
380
|
# additional conditions.
|
336
|
-
|
381
|
+
#
|
382
|
+
def where conditions, *substitutions
|
337
383
|
case conditions
|
338
384
|
when String
|
339
385
|
conditions = [replace_placeholders(conditions, *substitutions)]
|
@@ -391,64 +437,72 @@ module AWS
|
|
391
437
|
#
|
392
438
|
# @overload limit
|
393
439
|
# @return [Integer] Returns the current limit for the collection.
|
440
|
+
#
|
394
441
|
# @overload limit(value)
|
395
442
|
# @return [ItemCollection] Returns a collection with the given limit.
|
396
|
-
|
443
|
+
#
|
444
|
+
def limit *args
|
397
445
|
return @limit if args.empty?
|
398
446
|
collection_with(:limit => Integer(args.first))
|
399
447
|
end
|
448
|
+
alias_method :_limit, :limit # for Collection::Limitable
|
400
449
|
|
401
|
-
#
|
450
|
+
# Applies standard scope options (e.g. :where => 'foo') and removes them from
|
451
|
+
# the options hash by calling their method (e.g. by calling #where('foo')).
|
452
|
+
# Yields only if there were scope options to apply.
|
402
453
|
# @private
|
403
454
|
protected
|
404
455
|
def handle_query_options(*args)
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
456
|
+
|
457
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
458
|
+
|
459
|
+
if
|
460
|
+
query_options = options.keys & [:select, :where, :order, :limit] and
|
461
|
+
!query_options.empty?
|
462
|
+
then
|
463
|
+
collection = self
|
409
464
|
query_options.each do |query_option|
|
410
465
|
option_args = options[query_option]
|
411
466
|
option_args = [option_args] unless option_args.kind_of?(Array)
|
412
467
|
options.delete(query_option)
|
413
|
-
|
468
|
+
collection = collection.send(query_option, *option_args)
|
414
469
|
end
|
415
|
-
yield(c, *(args + [options]))
|
416
|
-
end
|
417
|
-
end
|
418
470
|
|
419
|
-
|
420
|
-
protected
|
421
|
-
def perform_select(options = {})
|
471
|
+
args << options
|
422
472
|
|
423
|
-
|
424
|
-
batch_size = options[:batch_size] ? Integer(options[:batch_size]) : nil
|
425
|
-
total = 0
|
426
|
-
|
427
|
-
begin
|
473
|
+
yield(collection, *args)
|
428
474
|
|
429
|
-
|
430
|
-
|
431
|
-
if batch_size
|
432
|
-
max = limit ? [limit - total, batch_size].min : batch_size
|
433
|
-
else
|
434
|
-
max = nil
|
435
|
-
end
|
475
|
+
end
|
476
|
+
end
|
436
477
|
|
437
|
-
|
478
|
+
protected
|
479
|
+
def _each_item next_token, max, options = {}, &block
|
438
480
|
|
439
|
-
|
481
|
+
handle_query_options(options) do |collection, opts|
|
482
|
+
return collection._each_item(next_token, max, opts, &block)
|
483
|
+
end
|
440
484
|
|
441
|
-
|
485
|
+
response = select_request(options, next_token, max)
|
442
486
|
|
443
|
-
|
487
|
+
if output_list == 'itemName()'
|
488
|
+
response.items.each do |item|
|
489
|
+
yield(self[item.name])
|
490
|
+
end
|
491
|
+
else
|
492
|
+
response.items.each do |item|
|
493
|
+
yield(ItemData.new(:domain => domain, :response_object => item))
|
494
|
+
end
|
495
|
+
end
|
444
496
|
|
445
|
-
|
497
|
+
response.next_token
|
498
|
+
|
446
499
|
end
|
447
500
|
|
448
501
|
protected
|
449
502
|
def select_request(options, next_token = nil, limit = nil)
|
503
|
+
|
450
504
|
opts = {}
|
451
|
-
opts[:select_expression] = select_expression(options
|
505
|
+
opts[:select_expression] = select_expression(options)
|
452
506
|
opts[:consistent_read] = consistent_read(options)
|
453
507
|
opts[:next_token] = next_token if next_token
|
454
508
|
|
@@ -459,57 +513,57 @@ module AWS
|
|
459
513
|
end
|
460
514
|
|
461
515
|
client.select(opts)
|
462
|
-
end
|
463
516
|
|
464
|
-
# @private
|
465
|
-
protected
|
466
|
-
def select_expression(output_list = nil)
|
467
|
-
output_list ||= "itemName()"
|
468
|
-
"SELECT #{output_list} FROM `#{domain.name}`" +
|
469
|
-
where_clause + order_by_clause + limit_clause
|
470
517
|
end
|
471
518
|
|
472
519
|
# @private
|
473
520
|
protected
|
474
|
-
def
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
521
|
+
def select_expression options = {}
|
522
|
+
expression = []
|
523
|
+
expression << "SELECT #{options[:output_list] || self.output_list}"
|
524
|
+
expression << "FROM `#{domain.name}`"
|
525
|
+
expression << where_clause
|
526
|
+
expression << order_by_clause
|
527
|
+
expression << limit_clause
|
528
|
+
expression.compact.join(' ')
|
480
529
|
end
|
481
530
|
|
482
531
|
# @private
|
483
532
|
protected
|
484
533
|
def where_clause
|
485
|
-
|
534
|
+
|
535
|
+
conditions = self.conditions.dup
|
536
|
+
|
486
537
|
if @not_null_attribute
|
487
|
-
|
488
|
-
end
|
489
|
-
if all_conditions.empty?
|
490
|
-
""
|
491
|
-
else
|
492
|
-
" WHERE " + all_conditions.join(" AND ")
|
538
|
+
conditions << coerce_attribute(@not_null_attribute) + " IS NOT NULL"
|
493
539
|
end
|
540
|
+
|
541
|
+
conditions.empty? ? nil : "WHERE #{conditions.join(" AND ")}"
|
542
|
+
|
494
543
|
end
|
495
544
|
|
496
545
|
# @private
|
497
546
|
protected
|
498
547
|
def order_by_clause
|
499
|
-
|
500
|
-
" ORDER BY " + sort_instructions
|
501
|
-
else
|
502
|
-
""
|
503
|
-
end
|
548
|
+
sort_instructions ? "ORDER BY #{sort_instructions}" : nil
|
504
549
|
end
|
505
550
|
|
506
551
|
# @private
|
507
552
|
protected
|
508
|
-
def
|
553
|
+
def limit_clause
|
554
|
+
limit ? "LIMIT #{limit}" : nil
|
555
|
+
end
|
556
|
+
|
557
|
+
# @private
|
558
|
+
protected
|
559
|
+
def collection_with options
|
509
560
|
ItemCollection.new(domain, {
|
510
|
-
:
|
561
|
+
:output_list => output_list,
|
511
562
|
:conditions => conditions,
|
512
|
-
:sort_instructions => sort_instructions
|
563
|
+
:sort_instructions => sort_instructions,
|
564
|
+
:not_null_attribute => @not_null_attribute,
|
565
|
+
:limit => limit,
|
566
|
+
}.merge(options))
|
513
567
|
end
|
514
568
|
|
515
569
|
# @private
|