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,384 @@
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
+ require 'date'
15
+
16
+ module AWS
17
+ module Record
18
+ module Attributes
19
+
20
+ # Base class for all of the AWS::Record attributes.
21
+ class BaseAttr
22
+
23
+ # @param [Symbol] Name of this attribute. It should be a name that
24
+ # is safe to use as a method.
25
+ # @param [Hash] options
26
+ # @option options [String] :persist_as Defaults to the name of the
27
+ # attribute. You can pass a string to specify what the attribute
28
+ # will be named in the backend storage.
29
+ # @option options [Boolean] :set (false) When true this attribute can
30
+ # accept multiple unique values.
31
+ def initialize name, options = {}
32
+ @name = name.to_s
33
+ @options = options.dup
34
+ if options[:set] and !self.class.allow_set?
35
+ raise ArgumentError, "invalid option :set for #{self.class}"
36
+ end
37
+ end
38
+
39
+ # @return [String] The name of this attribute
40
+ attr_reader :name
41
+
42
+ # @return [Hash] Attribute options passed to the constructor.
43
+ attr_reader :options
44
+
45
+ # @return [Boolean] Returns true if this attribute can have
46
+ # multiple values.
47
+ def set?
48
+ options[:set] ? true : false
49
+ end
50
+
51
+ # @return Returns the default value for this attribute.
52
+ def default_value
53
+ options[:default_value]
54
+ end
55
+
56
+ # @return [String] Returns the name this attribute will use
57
+ # in the storage backend.
58
+ def persist_as
59
+ (options[:persist_as] || @name).to_s
60
+ end
61
+
62
+ # @param [Mixed] A single value to type cast.
63
+ # @return [Mixed] Returns the type casted value.
64
+ def type_cast raw_value
65
+ self.class.type_cast(raw_value, options)
66
+ end
67
+
68
+ # @param [String] The serialized string value.
69
+ # @return [Mixed] Returns a deserialized type-casted value.
70
+ def deserialize serialized_value
71
+ self.class.deserialize(serialized_value, options)
72
+ end
73
+
74
+ # Takes the type casted value and serializes it
75
+ # @param [Mixed] A single value to serialize.
76
+ # @return [Mixed] Returns the serialized value.
77
+ def serialize type_casted_value
78
+ self.class.serialize(type_casted_value, options)
79
+ end
80
+
81
+ # @param [String] serialized_value The raw value returned from AWS.
82
+ # @return [Mixed] Returns the type-casted deserialized value.
83
+ def self.deserialize serialized_value, options = {}
84
+ self.type_cast(serialized_value, options)
85
+ end
86
+
87
+ # @return [Boolean] Returns true if this attribute type can be used
88
+ # with the +:set => true+ option. Certain attirbutes can not
89
+ # be represented with multiple values (like BooleanAttr).
90
+ def self.allow_set?
91
+ raise NotImplementedError
92
+ end
93
+
94
+ # @private
95
+ protected
96
+ def self.expect klass, value, &block
97
+ unless value.is_a?(klass)
98
+ raise ArgumentError, "expected a #{klass}, got #{value.class}"
99
+ end
100
+ yield if block_given?
101
+ end
102
+
103
+ end
104
+
105
+ class StringAttr < BaseAttr
106
+
107
+ # Returns the value cast to a string. Empty strings are returned as
108
+ # nil by default. Type casting is done by calling #to_s on the value.
109
+ #
110
+ # string_attr.type_cast(123)
111
+ # # => '123'
112
+ #
113
+ # string_attr.type_cast('')
114
+ # # => nil
115
+ #
116
+ # string_attr.type_cast('', :preserve_empty_strings => true)
117
+ # # => ''
118
+ #
119
+ # @param [Mixed] value
120
+ # @param [Hash] options
121
+ # @option options [Boolean] :preserve_empty_strings (false) When true,
122
+ # empty strings are preserved and not cast to nil.
123
+ # @return [String,nil] The type casted value.
124
+ def self.type_cast raw_value, options = {}
125
+ case raw_value
126
+ when nil then nil
127
+ when '' then options[:preserve_empty_strings] ? '' : nil
128
+ when String then raw_value
129
+ else raw_value.to_s
130
+ end
131
+ end
132
+
133
+ # Returns a serialized representation of the string value suitable for
134
+ # storing in SimpleDB.
135
+ # @param [String] string
136
+ # @param [Hash] options
137
+ # @return [String] The serialized string.
138
+ def self.serialize string, options = {}
139
+ unless string.is_a?(String)
140
+ msg = "expected a String value, got #{string.class}"
141
+ raise ArgumentError, msg
142
+ end
143
+ string
144
+ end
145
+
146
+ # @private
147
+ def self.allow_set?
148
+ true
149
+ end
150
+
151
+ end
152
+
153
+ class BooleanAttr < BaseAttr
154
+
155
+ def self.type_cast raw_value, options = {}
156
+ case raw_value
157
+ when nil then nil
158
+ when '' then nil
159
+ when false, 'false', '0', 0 then false
160
+ else true
161
+ end
162
+ end
163
+
164
+ def self.serialize boolean, options = {}
165
+ case boolean
166
+ when false then 0
167
+ when true then 1
168
+ else
169
+ msg = "expected a boolean value, got #{boolean.class}"
170
+ raise ArgumentError, msg
171
+ end
172
+ end
173
+
174
+ # @private
175
+ def self.allow_set?
176
+ false
177
+ end
178
+
179
+ end
180
+
181
+ class IntegerAttr < BaseAttr
182
+
183
+ # Returns value cast to an integer. Empty strings are cast to
184
+ # nil by default. Type casting is done by calling #to_i on the value.
185
+ #
186
+ # int_attribute.type_cast('123')
187
+ # #=> 123
188
+ #
189
+ # int_attribute.type_cast('')
190
+ # #=> nil
191
+ #
192
+ # @param [Mixed] value The value to type cast to an integer.
193
+ # @return [Integer,nil] Returns the type casted integer or nil
194
+ def self.type_cast raw_value, options = {}
195
+ case raw_value
196
+ when nil then nil
197
+ when '' then nil
198
+ when Integer then raw_value
199
+ else
200
+ raw_value.respond_to?(:to_i) ?
201
+ raw_value.to_i :
202
+ raw_value.to_s.to_i
203
+ end
204
+ end
205
+
206
+ # Returns a serialized representation of the integer value suitable for
207
+ # storing in SimpleDB.
208
+ #
209
+ # attribute.serialize(123)
210
+ # #=> '123'
211
+ #
212
+ # @param [Integer] integer The number to serialize.
213
+ # @param [Hash] options
214
+ # @return [String] A serialized representation of the integer.
215
+ def self.serialize integer, options = {}
216
+ expect(Integer, integer) { integer }
217
+ end
218
+
219
+ # @private
220
+ def self.allow_set?
221
+ true
222
+ end
223
+
224
+ end
225
+
226
+ class FloatAttr < BaseAttr
227
+
228
+ def self.type_cast raw_value, options = {}
229
+ case raw_value
230
+ when nil then nil
231
+ when '' then nil
232
+ when Float then raw_value
233
+ else
234
+ raw_value.respond_to?(:to_f) ?
235
+ raw_value.to_f :
236
+ raw_value.to_s.to_f
237
+ end
238
+ end
239
+
240
+ def self.serialize float, options = {}
241
+ expect(Float, float) { float }
242
+ end
243
+
244
+ # @private
245
+ def self.allow_set?
246
+ true
247
+ end
248
+
249
+ end
250
+
251
+ class DateAttr < BaseAttr
252
+
253
+ # Returns value cast to a Date object. Empty strings are cast to
254
+ # nil. Values are cast first to strings and then passed to
255
+ # Date.parse. Integers are treated as timestamps.
256
+ #
257
+ # date_attribute.type_cast('2000-01-02T10:11:12Z')
258
+ # #=> #<Date: 4903091/2,0,2299161>
259
+ #
260
+ # date_attribute.type_cast(1306170146)
261
+ # #<Date: 4911409/2,0,2299161>
262
+ #
263
+ # date_attribute.type_cast('')
264
+ # #=> nil
265
+ #
266
+ # date_attribute.type_cast(nil)
267
+ # #=> nil
268
+ #
269
+ # @param [Mixed] raw_value The value to cast to a Date object.
270
+ # @param [Hash] options
271
+ # @return [Date,nil]
272
+ def self.type_cast raw_value, options = {}
273
+ case raw_value
274
+ when nil then nil
275
+ when '' then nil
276
+ when Date then raw_value
277
+ when Integer then
278
+ begin
279
+ Date.parse(Time.at(raw_value).to_s) # assumed timestamp
280
+ rescue
281
+ nil
282
+ end
283
+ else
284
+ begin
285
+ Date.parse(raw_value.to_s) # Time, DateTime or String
286
+ rescue
287
+ nil
288
+ end
289
+ end
290
+ end
291
+
292
+ # Returns a Date object encoded as a string (suitable for sorting).
293
+ #
294
+ # attribute.serialize(DateTime.parse('2001-01-01'))
295
+ # #=> '2001-01-01'
296
+ #
297
+ # @param [Date] datetime The date to serialize.
298
+ #
299
+ # @param [Hash] options
300
+ #
301
+ # @return [String] Returns the date object serialized to a string
302
+ # ('YYYY-MM-DD').
303
+ #
304
+ def self.serialize date, options = {}
305
+ unless date.is_a?(Date)
306
+ raise ArgumentError, "expected a Date value, got #{date.class}"
307
+ end
308
+ date.strftime('%Y-%m-%d')
309
+ end
310
+
311
+ # @private
312
+ def self.allow_set?
313
+ true
314
+ end
315
+
316
+ end
317
+
318
+ class DateTimeAttr < BaseAttr
319
+
320
+ # Returns value cast to a DateTime object. Empty strings are cast to
321
+ # nil. Values are cast first to strings and then passed to
322
+ # DateTime.parse. Integers are treated as timestamps.
323
+ #
324
+ # datetime_attribute.type_cast('2000-01-02')
325
+ # #=> #<DateTime: 4903091/2,0,2299161>
326
+ #
327
+ # datetime_attribute.type_cast(1306170146)
328
+ # #<DateTime: 106086465073/43200,-7/24,2299161>
329
+ #
330
+ # datetime_attribute.type_cast('')
331
+ # #=> nil
332
+ #
333
+ # datetime_attribute.type_cast(nil)
334
+ # #=> nil
335
+ #
336
+ # @param [Mixed] raw_value The value to cast to a DateTime object.
337
+ # @param [Hash] options
338
+ # @return [DateTime,nil]
339
+ def self.type_cast raw_value, options = {}
340
+ case raw_value
341
+ when nil then nil
342
+ when '' then nil
343
+ when DateTime then raw_value
344
+ when Integer then
345
+ begin
346
+ DateTime.parse(Time.at(raw_value).to_s) # timestamp
347
+ rescue
348
+ nil
349
+ end
350
+ else
351
+ begin
352
+ DateTime.parse(raw_value.to_s) # Time, Date or String
353
+ rescue
354
+ nil
355
+ end
356
+ end
357
+ end
358
+
359
+ # Returns a DateTime object encoded as a string (suitable for sorting).
360
+ #
361
+ # attribute.serialize(DateTime.parse('2001-01-01'))
362
+ # #=> '2001-01-01T00:00:00:Z)
363
+ #
364
+ # @param [DateTime] datetime The datetime object to serialize.
365
+ # @param [Hash] options
366
+ # @return [String] Returns the datetime object serialized to a string
367
+ # in ISO8601 format (e.g. '2011-01-02T10:11:12Z')
368
+ def self.serialize datetime, options = {}
369
+ unless datetime.is_a?(DateTime)
370
+ msg = "expected a DateTime value, got #{datetime.class}"
371
+ raise ArgumentError, msg
372
+ end
373
+ datetime.strftime('%Y-%m-%dT%H:%M:%S%Z')
374
+ end
375
+
376
+ # @private
377
+ def self.allow_set?
378
+ true
379
+ end
380
+
381
+ end
382
+ end
383
+ end
384
+ end
@@ -14,7 +14,6 @@
14
14
  module AWS
15
15
  module Record
16
16
 
17
-
18
17
  # Provides a way to track changes in your records.
19
18
  #
20
19
  # my_book = Book['bookid']
@@ -14,14 +14,6 @@
14
14
  module AWS
15
15
  module Record
16
16
 
17
- class Base
18
-
19
- def errors
20
- @errors ||= Errors.new
21
- end
22
-
23
- end
24
-
25
17
  class Errors < Core::IndifferentHash
26
18
 
27
19
  include Enumerable
@@ -0,0 +1,163 @@
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
+ require 'aws/record/abstract_base'
15
+ require 'aws/record/hash_model/scope'
16
+ require 'aws/record/hash_model/attributes'
17
+ require 'aws/record/hash_model/finder_methods'
18
+
19
+ module AWS
20
+ module Record
21
+ class HashModel
22
+
23
+ extend AbstractBase
24
+
25
+ class << self
26
+
27
+ # Creates the DynamoDB table that is configured for this class.
28
+ #
29
+ # class Product < AWS::Record::HashModel
30
+ # end
31
+ #
32
+ # # create the table 'Product' with 10 read/write capacity units
33
+ # Product.create_table 10, 10
34
+ #
35
+ # If you shard you data across multiple tables, you can specify the
36
+ # shard name:
37
+ #
38
+ # # create two tables, with the given names
39
+ # Product.create_table 500, 10, :shard_name => 'products-1'
40
+ # Product.create_table 500, 10, :shard_name => 'products-2'
41
+ #
42
+ # If you share a single AWS account with multiple applications, you
43
+ # can provide a table prefix to group tables and to avoid name
44
+ # collisions:
45
+ #
46
+ # AWS::Record.table_prefix = 'myapp-'
47
+ #
48
+ # # creates the table 'myapp-Product'
49
+ # Product.create_table 250, 50
50
+ #
51
+ # # creates the table 'myapp-products-1'
52
+ # Product.create_table 250, 50, :shard_name => 'products-1'
53
+ #
54
+ # @param [Integer] read_capacity_units
55
+ # See {DynamoDB::TableCollection#create} for more information.
56
+ #
57
+ # @param [Integer] write_capacity_units
58
+ # See {DynamoDB::TableCollection#create} for more information.
59
+ #
60
+ # @param [Hash] options Hash of options passed to
61
+ # {DynamoDB::TableCollection#create}.
62
+ #
63
+ # @option options [String] :shard_name Defaults to the class name. The
64
+ # shard name will be prefixed with {AWS::Record.table_prefix},
65
+ # and that becomes the table name.
66
+ #
67
+ # @return [DynamoDB::Table]
68
+ #
69
+ def create_table read_capacity_units, write_capacity_units, options = {}
70
+
71
+ table_name = dynamo_db_table_name(options[:shard_name])
72
+
73
+ create_opts = { :hash_key => [:id, :string] }
74
+
75
+ dynamo_db.tables.create(
76
+ table_name,
77
+ read_capacity_units,
78
+ write_capacity_units,
79
+ create_opts)
80
+
81
+ end
82
+
83
+ # @return [DynamoDB::Table]
84
+ # @private
85
+ def dynamo_db_table shard_name = nil
86
+ table = dynamo_db.tables[dynamo_db_table_name(shard_name)]
87
+ table.hash_key = [:id, :string]
88
+ table
89
+ end
90
+
91
+ protected
92
+ def dynamo_db_table_name shard_name = nil
93
+ "#{Record.table_prefix}#{self.shard_name(shard_name)}"
94
+ end
95
+
96
+ protected
97
+ def dynamo_db
98
+ AWS::DynamoDB.new(
99
+ :dynamo_db_endpoint => 'bigbird-sdk.amazon.com',
100
+ :use_ssl => false)
101
+ end
102
+
103
+ end
104
+
105
+ # @return [DynamoDB::Item] Returns a reference to the item as stored in
106
+ # simple db.
107
+ # @private
108
+ private
109
+ def dynamo_db_item
110
+ dynamo_db_table.items[id]
111
+ end
112
+
113
+ # @return [SimpleDB::Domain] Returns the domain this record is
114
+ # persisted to or will be persisted to.
115
+ private
116
+ def dynamo_db_table
117
+ self.class.dynamo_db_table(shard)
118
+ end
119
+
120
+ private
121
+ def create_storage
122
+ attributes = serialize_attributes.merge('id' => @_id)
123
+ dynamo_db_table.items.create(attributes, opt_lock_conditions)
124
+ end
125
+
126
+ private
127
+ def update_storage
128
+ # Only enumerating dirty (i.e. changed) attributes. Empty
129
+ # (nil and empty set) values are deleted, the others are replaced.
130
+ dynamo_db_item.attributes.update(opt_lock_conditions) do |u|
131
+ changed.each do |attr_name|
132
+ attribute = self.class.attribute_for(attr_name)
133
+ value = serialize_attribute(attribute, @_data[attr_name])
134
+ if value.nil? or value == []
135
+ u.delete(attr_name)
136
+ else
137
+ u.set(attr_name => value)
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+ def delete_storage
145
+ dynamo_db_item.delete(opt_lock_conditions)
146
+ end
147
+
148
+ private
149
+ def deserialize_item_data data
150
+ data.inject({}) do |hash,(attr_name,value)|
151
+ if attribute = self.class.attributes[attr_name]
152
+ hash[attr_name] = value.is_a?(Set) ?
153
+ value.map{|v| attribute.deserialize(v) } :
154
+ attribute.deserialize(value)
155
+ end
156
+ hash
157
+ end
158
+ end
159
+
160
+ end
161
+
162
+ end
163
+ end