aws-sdk 1.2.6 → 1.3.0

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