aws-sdk 1.1.4 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|