aws-sdk 1.2.6 → 1.3.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.
Files changed (60) hide show
  1. data/lib/aws.rb +2 -0
  2. data/lib/aws/api_config/DynamoDB-2011-12-05.yml +721 -0
  3. data/lib/aws/core.rb +10 -1
  4. data/lib/aws/core/client.rb +17 -12
  5. data/lib/aws/core/configuration.rb +13 -3
  6. data/lib/aws/core/configured_json_client_methods.rb +71 -0
  7. data/lib/aws/core/lazy_error_classes.rb +7 -2
  8. data/lib/aws/core/option_grammar.rb +67 -13
  9. data/lib/aws/core/resource.rb +9 -1
  10. data/lib/aws/core/session_signer.rb +95 -0
  11. data/lib/aws/dynamo_db.rb +169 -0
  12. data/lib/aws/dynamo_db/attribute_collection.rb +460 -0
  13. data/lib/aws/dynamo_db/batch_get.rb +206 -0
  14. data/lib/aws/dynamo_db/client.rb +119 -0
  15. data/lib/aws/dynamo_db/config.rb +20 -0
  16. data/lib/aws/dynamo_db/errors.rb +57 -0
  17. data/lib/aws/dynamo_db/expectations.rb +40 -0
  18. data/lib/aws/dynamo_db/item.rb +130 -0
  19. data/lib/aws/dynamo_db/item_collection.rb +837 -0
  20. data/lib/aws/{record/optimistic_locking.rb → dynamo_db/item_data.rb} +9 -12
  21. data/lib/aws/{record/attributes/boolean.rb → dynamo_db/keys.rb} +15 -23
  22. data/lib/aws/dynamo_db/primary_key_element.rb +47 -0
  23. data/lib/aws/dynamo_db/request.rb +78 -0
  24. data/lib/aws/{record/attributes/float.rb → dynamo_db/resource.rb} +10 -25
  25. data/lib/aws/dynamo_db/table.rb +418 -0
  26. data/lib/aws/dynamo_db/table_collection.rb +165 -0
  27. data/lib/aws/dynamo_db/types.rb +86 -0
  28. data/lib/aws/ec2/resource_tag_collection.rb +3 -1
  29. data/lib/aws/record.rb +36 -8
  30. data/lib/aws/record/abstract_base.rb +642 -0
  31. data/lib/aws/record/attributes.rb +384 -0
  32. data/lib/aws/record/dirty_tracking.rb +0 -1
  33. data/lib/aws/record/errors.rb +0 -8
  34. data/lib/aws/record/hash_model.rb +163 -0
  35. data/lib/aws/record/hash_model/attributes.rb +182 -0
  36. data/lib/aws/record/hash_model/finder_methods.rb +178 -0
  37. data/lib/aws/record/hash_model/scope.rb +108 -0
  38. data/lib/aws/record/model.rb +429 -0
  39. data/lib/aws/record/model/attributes.rb +377 -0
  40. data/lib/aws/record/model/finder_methods.rb +232 -0
  41. data/lib/aws/record/model/scope.rb +213 -0
  42. data/lib/aws/record/scope.rb +43 -169
  43. data/lib/aws/record/validations.rb +11 -11
  44. data/lib/aws/s3/client.rb +9 -6
  45. data/lib/aws/s3/object_collection.rb +1 -1
  46. data/lib/aws/simple_db/expect_condition_option.rb +1 -1
  47. data/lib/aws/simple_db/item_collection.rb +5 -3
  48. data/lib/aws/sts/client.rb +9 -0
  49. metadata +73 -30
  50. data/lib/aws/record/attribute.rb +0 -94
  51. data/lib/aws/record/attribute_macros.rb +0 -312
  52. data/lib/aws/record/attributes/date.rb +0 -89
  53. data/lib/aws/record/attributes/datetime.rb +0 -86
  54. data/lib/aws/record/attributes/integer.rb +0 -68
  55. data/lib/aws/record/attributes/sortable_float.rb +0 -60
  56. data/lib/aws/record/attributes/sortable_integer.rb +0 -95
  57. data/lib/aws/record/attributes/string.rb +0 -69
  58. data/lib/aws/record/base.rb +0 -828
  59. data/lib/aws/record/finder_methods.rb +0 -230
  60. data/lib/aws/record/scopes.rb +0 -55
@@ -0,0 +1,169 @@
1
+ # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+
16
+ # Provides a high-level interface for using DynamoDB.
17
+ #
18
+ # dynamo_db = AWS::DynamoDB.new(
19
+ # :access_key_id => '...',
20
+ # :secret_access_key => '...',
21
+ # :session_token => '...')
22
+ #
23
+ # = Credentials
24
+ #
25
+ # Amazon DynamoDB requires that all requests are made with short-term
26
+ # credentials (e.g. requires a session token).
27
+ #
28
+ # @note If you make a request using AWS::DynamoDB with long-term credentials
29
+ # a request is made to Amazon STS for temproary session credentials.
30
+ # These will be cached in the process and re-used.
31
+ #
32
+ # = Tables
33
+ #
34
+ # Tables contain items, and organize information into discrete
35
+ # areas. All items in the table have the same primary key
36
+ # scheme. You designate the attribute name (or names) to use for the
37
+ # primary key when you create a table, and the table requires each
38
+ # item in the table to have a unique primary key value. The first
39
+ # step in writing data to DynamoDB is to create a table and
40
+ # designate a table name with a primary key.
41
+ #
42
+ # table = dynamo_db.tables.create(
43
+ # "MyTable",
44
+ # :hash_key => [:id, :string]
45
+ # )
46
+ # sleep 1 while t.status == :creating
47
+ #
48
+ # See {Table} and {TableCollection} for more information on creating
49
+ # and managing tables.
50
+ #
51
+ # = Items and Attributes
52
+ #
53
+ # An item is a collection of one or more attributes, where each
54
+ # attribute has a string name and a string, number, string set or
55
+ # number set value.
56
+ #
57
+ # The identity of an item consists of its hash key value and -- if
58
+ # the table's schema includes a range key -- its range key value.
59
+ #
60
+ # item = table.items.put(:id => "abc123")
61
+ # item.hash_value # => "abc123"
62
+ # item.attributes.set(
63
+ # :colors => ["red", "blue"],
64
+ # :numbers => [12, 24]
65
+ # )
66
+ #
67
+ # See {Item} and {ItemCollection} for more information on creating
68
+ # and managing items. For more information on managing attributes,
69
+ # see {AttributeCollection}.
70
+ #
71
+ # = Examples
72
+ #
73
+ # # create a table (10 read and 5 write capacity units) with the
74
+ # # default schema (id string hash key)
75
+ # dynamo_db = AWS::DynamoDB.new
76
+ # table = dynamo_db.tables.create('my-table', 10, 5)
77
+ # sleep 1 while table.status == :creating
78
+ # table.status #=> :active
79
+ #
80
+ # # get an existing table by name and specify its hash key
81
+ # table = dynamo_db.tables['another-table']
82
+ # table.hash_key = [:id, :number]
83
+ #
84
+ # # add an item
85
+ # item = table.items.create('id' => 12345, 'foo' => 'bar')
86
+ #
87
+ # # add attributes to an item
88
+ # item.attributes.add 'category' => %w(demo), 'tags' => %w(sample item)
89
+ #
90
+ # # update an item with mixed add, delete, update
91
+ # item.attributes.update do |u|
92
+ # u.add 'colors' => %w(red)
93
+ # u.set 'category' => 'demo-category'
94
+ # u.delete 'foo'
95
+ # end
96
+ #
97
+ # # delete attributes
98
+ # item.attributes.delete 'colors', 'category'
99
+ #
100
+ # # get attributes
101
+ # item.attributes.to_h
102
+ # #=> {"id"=>#<BigDecimal:10155f5d0,'0.12345E5',9(18)>, "tags"=>#<Set: {"item", "sample"}>}
103
+ #
104
+ # # delete an item and all of its attributes
105
+ # item.delete
106
+ #
107
+ class DynamoDB
108
+
109
+ AWS.register_autoloads(self, 'aws/dynamo_db') do
110
+ autoload :AttributeCollection, 'attribute_collection'
111
+ autoload :BatchGet, 'batch_get'
112
+ autoload :Client, 'client'
113
+ autoload :Errors, 'errors'
114
+ autoload :Expectations, 'expectations'
115
+ autoload :Item, 'item'
116
+ autoload :ItemData, 'item_data'
117
+ autoload :ItemCollection, 'item_collection'
118
+ autoload :Keys, 'keys'
119
+ autoload :PrimaryKeyElement, 'primary_key_element'
120
+ autoload :Request, 'request'
121
+ autoload :Resource, 'resource'
122
+ autoload :Table, 'table'
123
+ autoload :TableCollection, 'table_collection'
124
+ autoload :Types, 'types'
125
+ end
126
+
127
+ include Core::ServiceInterface
128
+
129
+ # Returns a collection representing all the tables in your account.
130
+ #
131
+ # @return [TableCollection]
132
+ def tables
133
+ TableCollection.new(:config => config)
134
+ end
135
+
136
+ # Request attributes for items spanning multiple tables. You configure
137
+ # you batch get request using a block:
138
+ #
139
+ # attributes = dynamo_db.batch_get do |batch|
140
+ # # call methods on batch specify tables, attributes and items
141
+ # # ...
142
+ # end
143
+ #
144
+ # The value returned by #batch_get is an enumerable object that yields
145
+ # the table name (as a string) and a hash of attributes. The
146
+ # enumerable yields once per item received in the batch get.
147
+ #
148
+ # == Configuring the batch
149
+ #
150
+ # You can call two methods on the yielded batch object:
151
+ #
152
+ # * #table
153
+ # * #items
154
+ #
155
+ # For more information on these methods, see {BatchGet}.
156
+ #
157
+ # @yield [String, Hash] Yields the table name as a string and a hash
158
+ # of attributes for each item received in the bach get request.
159
+ #
160
+ # @return [Enumerable]
161
+ #
162
+ def batch_get &block
163
+ batch = BatchGet.new(:config => config)
164
+ yield(batch)
165
+ batch.enumerator
166
+ end
167
+
168
+ end
169
+ end
@@ -0,0 +1,460 @@
1
+ # Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ module AWS
15
+ class DynamoDB
16
+
17
+ # Represents the attributes of a DynamoDB item. An attribute is a
18
+ # name-value pair. The name must be a string, but the value can be
19
+ # a string, number, string set, or number set. Attribute values
20
+ # cannot be null or empty.
21
+ #
22
+ # @note The SDK always returns numbers as BigDecimal objects and
23
+ # sets as Set objects; however, on input it accepts any numeric
24
+ # type for number attributes and either Arrays or Sets for set
25
+ # attributes.
26
+ #
27
+ # @example Retrieving specific attributes of an item
28
+ # (title, description) =
29
+ # item.attributes.values_at(:title, :description)
30
+ #
31
+ # @example Retrieving all attributes in hash form
32
+ # item.attributes.to_h
33
+ #
34
+ # @example Replacing the value of an attribute
35
+ # item.attributes[:title] = "Automobiles"
36
+ #
37
+ # @example Doing a mixed update of item attributes in a single operation
38
+ # item.attributes.update do |u|
39
+ #
40
+ # # add 12 to the (numeric) value of "views"
41
+ # u.add(:views => 12)
42
+ #
43
+ # # delete attributes
44
+ # u.delete(:foo, :bar)
45
+ #
46
+ # # delete values out of a set attribute
47
+ # u.delete(:colors => ["red", "blue"])
48
+ #
49
+ # # replace values
50
+ # u.set(:title => "More Automobiles")
51
+ # end
52
+ #
53
+ # @example Returning overwritten values
54
+ # item.attributes.to_h # => { "foo" => "bar",
55
+ # "name" => "fred" }
56
+ # item.attributes.set(
57
+ # { "foo" => "baz" },
58
+ # :return => :updated_old
59
+ # ) # => { "foo" => "bar" }
60
+ #
61
+ # @example Performing a conditional update
62
+ # item.set({ :version => 3 }, :if => { :version => 2 })
63
+ class AttributeCollection
64
+
65
+ include Core::Model
66
+ include Enumerable
67
+ include Types
68
+ include Keys
69
+ include Expectations
70
+
71
+ # @return [Item] The item to which these attributes belong.
72
+ attr_reader :item
73
+
74
+ # @private
75
+ def initialize(item, opts = {})
76
+ @item = item
77
+ super
78
+ end
79
+
80
+ # Behaves like Hash#each; yields each attribute as a name/value
81
+ # pair.
82
+ #
83
+ # attributes.each { |(name, value)| puts "#{name} = #{value}" }
84
+ #
85
+ # attributes.each { |name, value| puts "#{name} = #{value}" }
86
+ #
87
+ # @param (see #to_h)
88
+ #
89
+ # @option options (see #to_h)
90
+ def each(options = {}, &block)
91
+ to_h(options).each(&block)
92
+ end
93
+
94
+ # @yieldparam [String] name Each attribute name.
95
+ def each_key(options = {})
96
+ each(options) { |k, v| yield(k) if block_given? }
97
+ end
98
+
99
+ # @yieldparam value Each attribute value belonging to the item.
100
+ # Values will be of type String, BigDecimal, Set<String> or
101
+ # Set<BigDecimal>.
102
+ def each_value(options = {})
103
+ each(options) { |k, v| yield(v) if block_given? }
104
+ end
105
+
106
+ # Retrieves the value of a single attribute.
107
+ #
108
+ # @param [String, Symbol] attribute The name of the attribute to
109
+ # get.
110
+ #
111
+ # @return The value of the specified attribute, which may be a
112
+ # String, BigDecimal, Set<String> or Set<BigDecimal>.
113
+ def [] attribute
114
+ attribute = attribute.to_s
115
+ response_attributes = get_item(:attributes_to_get => [attribute])
116
+ value_from_response(response_attributes[attribute])
117
+ end
118
+
119
+ # Replaces the value of a single attribute.
120
+ #
121
+ # @param [String, Symbol] attribute The name of the attribute to
122
+ # replace.
123
+ #
124
+ # @param value The new value to set. This may be a String,
125
+ # Numeric, Set or Array of String objects, or Set or Array of
126
+ # Numeric objects. Mixed types are not allowed in sets, and
127
+ # neither String values nor set values may be empty. Setting
128
+ # an attribute to nil is the same as deleting the attribute.
129
+ #
130
+ # @return The new value of the attribute.
131
+ def []= attribute, value
132
+ set(attribute => value)
133
+ value
134
+ end
135
+
136
+ # Replaces the values of one or more attributes.
137
+ #
138
+ # @param [Hash] attributes The attributes to replace. The keys
139
+ # of the hash may be strings or symbols. The values may be of
140
+ # type String, Numeric, Set or Array of String objects, or Set
141
+ # or Array of Numeric objects. Mixed types are not allowed in
142
+ # sets, and neither String values nor set values may be empty.
143
+ # Setting an attribute to nil is the same as deleting the
144
+ # attribute.
145
+ #
146
+ # @param [Hash] options Options for updating the item.
147
+ #
148
+ # @option options (see #update)
149
+ def set attributes, options = {}
150
+ update(options) { |u| u.set(attributes) }
151
+ end
152
+ alias_method :merge!, :set
153
+ alias_method :put, :set
154
+
155
+ # Adds to the values of one or more attributes. Each attribute
156
+ # must be a set or number in the original item, and each input
157
+ # value must have the same type as the value in the original
158
+ # item. For example, it is invalid to add a single number to a
159
+ # set of numbers, but it is valid to add a set containing a
160
+ # single number to another set of numbers.
161
+ #
162
+ # When the original attribute is a set, the values provided to
163
+ # this method are added to that set. When the original
164
+ # attribute is a number, the original value is incremented by
165
+ # the numeric value provided to this method. For example:
166
+ #
167
+ # item = table.items.put(
168
+ # :id => "abc123",
169
+ # :colors => ["red", "white"],
170
+ # :age => 3
171
+ # )
172
+ # item.attributes.add(
173
+ # { :colors => ["muave"],
174
+ # :age => 1 },
175
+ # :return => :updated_new
176
+ # ) # => { "colors" => Set["red", "white", "mauve"],
177
+ # # "age" => 4 }
178
+ #
179
+ # @param [Hash] attributes The attribute values to add. The
180
+ # keys of the hash may be strings or symbols. The values may
181
+ # be of type Numeric, Set or Array of String objects, or Set
182
+ # or Array of Numeric objects. Mixed types are not allowed in
183
+ # sets, and neither String values nor set values may be empty.
184
+ # Single string values are not allowed for this method, since
185
+ # DynamoDB does not currently support adding a string to
186
+ # another string.
187
+ #
188
+ # @param [Hash] options Options for updating the item.
189
+ #
190
+ # @option options (see #update)
191
+ def add attributes, options = {}
192
+ update(options) { |u| u.add(attributes) }
193
+ end
194
+
195
+ # @overload delete *attributes
196
+ #
197
+ # Deletes attributes from the item. Each argument must be a
198
+ # string or symbol specifying the name of the attribute to
199
+ # delete. The last argument may be a hash containing options
200
+ # for the update. See {#update} for more information about
201
+ # what options are accepted.
202
+ #
203
+ # @overload delete attributes, options = {}
204
+ #
205
+ # Deletes specific values from one or more attributes, whose
206
+ # original values must be sets.
207
+ #
208
+ # @param [Hash] attributes The attribute values to delete.
209
+ # The keys of the hash may be strings or symbols. The
210
+ # values must be arrays or Sets of numbers or strings.
211
+ # Mixed types are not allowed in sets. The type of each
212
+ # member in a set must match the type of the members in the
213
+ # original attribute value.
214
+ #
215
+ # @param [Hash] options Options for updating the item.
216
+ #
217
+ # @option options (see #update)
218
+ def delete *args
219
+ if args.first.kind_of?(Hash)
220
+ delete_args = [args.shift]
221
+ else
222
+ delete_args = args
223
+ end
224
+ options = args.pop if args.last.kind_of?(Hash)
225
+ update(options || {}) { |u| u.delete(*delete_args) }
226
+ end
227
+
228
+ # Used to build a batch of updates to an item's attributes. See
229
+ # {AttributeCollection#update} for more information.
230
+ class UpdateBuilder
231
+
232
+ # @private
233
+ attr_reader :updates
234
+
235
+ include Types
236
+
237
+ # @private
238
+ def initialize
239
+ @updates = {}
240
+ end
241
+
242
+ # Replaces the values of one or more attributes. See
243
+ # {AttributeCollection#set} for more information.
244
+ def set attributes
245
+ to_delete = []
246
+ attributes = attributes.inject({}) do |attributes, (name, value)|
247
+ if value == nil
248
+ to_delete << name
249
+ else
250
+ attributes[name] = value
251
+ end
252
+ attributes
253
+ end
254
+ attribute_updates("PUT", attributes)
255
+ delete(*to_delete)
256
+ end
257
+ alias_method :put, :set
258
+ alias_method :merge!, :set
259
+
260
+ # Adds to the values of one or more attributes. See
261
+ # {AttributeCollection#add} for more information.
262
+ def add attributes
263
+ attribute_updates("ADD", attributes)
264
+ end
265
+
266
+
267
+ # Deletes one or more attributes or attribute values. See
268
+ # {AttributeCollection#delete} for more information.
269
+ def delete *args
270
+ if args.first.kind_of?(Hash)
271
+ attribute_updates("DELETE",
272
+ args.shift,
273
+ :setify => true)
274
+ else
275
+ add_updates(args.inject({}) do |u, name|
276
+ u.update(name.to_s => {
277
+ :action => "DELETE"
278
+ })
279
+ end)
280
+ end
281
+ end
282
+
283
+ private
284
+ def attribute_updates(action, attributes, our_opts = {})
285
+ new_updates = attributes.inject({}) do |new_updates, (name, value)|
286
+ name = name.to_s
287
+ context = "in value for attribute #{name}"
288
+ value = [value].flatten if our_opts[:setify]
289
+ new_updates.update(name => {
290
+ :action => action,
291
+ :value =>
292
+ format_attribute_value(value, context)
293
+ })
294
+ end
295
+ add_updates(new_updates)
296
+ end
297
+
298
+ private
299
+ def add_updates(new_updates)
300
+ updates.merge!(new_updates) do |name, old, new|
301
+ raise ArgumentError, "conflicting updates for attribute #{name}"
302
+ end
303
+ end
304
+
305
+ end
306
+
307
+ # Updates multiple attributes in a single operation. This is
308
+ # more efficient than performing each type of update in
309
+ # sequence, and it also allows you to group different kinds of
310
+ # updates into an atomic operation.
311
+ #
312
+ # item.attributes.update do |u|
313
+ #
314
+ # # add 12 to the (numeric) value of "views"
315
+ # u.add(:views => 12)
316
+ #
317
+ # # delete attributes
318
+ # u.delete(:foo, :bar)
319
+ #
320
+ # # delete values out of a set attribute
321
+ # u.delete(:colors => ["red", "blue"])
322
+ #
323
+ # # replace values
324
+ # u.set(:title => "More Automobiles")
325
+ # end
326
+ #
327
+ # @param [Hash] options Options for updating the item.
328
+ #
329
+ # @option options [Hash] :if Designates a conditional update.
330
+ # The operation will fail unless the item exists and has the
331
+ # attributes in the value for this option. For example:
332
+ #
333
+ # # throws DynamoDB::Errors::ConditionalCheckFailedException
334
+ # # unless the item has "color" set to "red"
335
+ # item.attributes.update(:if => { :color => "red" }) do |u|
336
+ # # ...
337
+ # end
338
+ #
339
+ # @option options [String, Symbol, Array] :unless_exists A name
340
+ # or collection of attribute names; if the item already exists
341
+ # and has a value for any of these attributes, this method
342
+ # will raise
343
+ # +DynamoDB::Errors::ConditionalCheckFailedException+. For example:
344
+ #
345
+ # item.attributes.update(:unless_exists => :color) do |u|
346
+ # # ...
347
+ # end
348
+ #
349
+ # @option options [Symbol] :return (+:none+) Changes the return
350
+ # value of the method. Valid values:
351
+ #
352
+ # [+:none+] Return +nil+
353
+ #
354
+ # [+:all_old+] Returns a hash containing all of the original
355
+ # values of the attributes before the update, or
356
+ # +nil+ if the item did not exist at the time of
357
+ # the update.
358
+ #
359
+ # [+:updated_old+] Returns a hash containing the original
360
+ # values of the attributes that were modified
361
+ # as part of this operation. This includes
362
+ # attributes that were deleted, and
363
+ # set-valued attributes whose member values
364
+ # were deleted.
365
+ #
366
+ # [+:updated_new+] Returns a hash containing the new values of
367
+ # the attributes that were modified as part
368
+ # of this operation. This includes
369
+ # set-valued attributes whose member values
370
+ # were deleted.
371
+ #
372
+ # [+:all_new+] Returns a hash containing the new values of all
373
+ # of the attributes.
374
+ #
375
+ # @yieldparam [UpdateBuilder] builder A handle for describing
376
+ # the update.
377
+ #
378
+ # @note DnamoDB allows only one update per attribute in a
379
+ # single operation. This method will raise an ArgumentError
380
+ # if multiple updates are described for a single attribute.
381
+ #
382
+ # @return [nil] See the documentation for the +:return+ option
383
+ # above.
384
+ def update(options = {})
385
+ builder = UpdateBuilder.new
386
+ yield(builder)
387
+ do_updates({ :attribute_updates => builder.updates },
388
+ options)
389
+ end
390
+
391
+ # Retrieves the values of the specified attributes.
392
+ #
393
+ # @param [Array<String, Symbol>] attributes The names of the
394
+ # attributes to retrieve. The last argument may be a hash of
395
+ # options for retrieving attributes from the item. Currently
396
+ # the only supported option is +:consistent_read+; If set to
397
+ # true, then a consistent read is issued, otherwise an
398
+ # eventually consistent read is used.
399
+ #
400
+ # @return [Array] An array in which each member contains the
401
+ # value of the attribute at that index in the argument list.
402
+ # Values may be Strings, BigDecimals, Sets of Strings or Sets
403
+ # or BigDecimals. If a requested attribute does not exist,
404
+ # the corresponding member of the output array will be +nil+.
405
+ def values_at(*attributes)
406
+ options = {}
407
+ options = attributes.pop if attributes.last.kind_of?(Hash)
408
+
409
+ return [] if attributes.empty?
410
+
411
+ attributes.map! { |a| a.to_s }
412
+ response_attributes =
413
+ get_item(options, :attributes_to_get => attributes)
414
+
415
+ values_from_response_hash(response_attributes).
416
+ values_at(*attributes)
417
+ end
418
+
419
+ # @param [Hash] options Options for retrieving attributes from
420
+ # the item.
421
+ #
422
+ # @option options [Boolean] :consistent_read If set to true,
423
+ # then a consistent read is issued, otherwise an eventually
424
+ # consistent read is used.
425
+ def to_h options = {}
426
+ values_from_response_hash(get_item(options))
427
+ end
428
+
429
+ private
430
+ def item_key_options(options = {})
431
+ super(item, options)
432
+ end
433
+
434
+ private
435
+ def get_item(their_options, our_options = {})
436
+ options = their_options.merge(our_options)
437
+ resp = client.get_item(item_key_options(options))
438
+ resp.data['Item'] || {}
439
+ end
440
+
441
+ private
442
+ def do_updates(client_opts, options)
443
+ return nil if client_opts[:attribute_updates].empty?
444
+
445
+ client_opts[:return_values] = options[:return].to_s.upcase if
446
+ options[:return]
447
+
448
+ expected = expect_conditions(options)
449
+ client_opts[:expected] = expected unless expected.empty?
450
+
451
+ resp = client.update_item(item_key_options(client_opts))
452
+
453
+ values_from_response_hash(resp.data["Attributes"]) if
454
+ options[:return] and resp.data["Attributes"]
455
+ end
456
+
457
+ end
458
+
459
+ end
460
+ end