aws-record 1.0.0.pre.9 → 1.0.0.pre.10
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.
- checksums.yaml +4 -4
- data/lib/aws-record.rb +3 -0
- data/lib/aws-record/record.rb +6 -0
- data/lib/aws-record/record/attribute.rb +0 -12
- data/lib/aws-record/record/attributes.rb +27 -164
- data/lib/aws-record/record/dirty_tracking.rb +12 -103
- data/lib/aws-record/record/item_collection.rb +3 -2
- data/lib/aws-record/record/item_data.rb +123 -0
- data/lib/aws-record/record/item_operations.rb +21 -35
- data/lib/aws-record/record/key_attributes.rb +54 -0
- data/lib/aws-record/record/model_attributes.rb +99 -0
- data/lib/aws-record/record/secondary_indexes.rb +5 -5
- data/lib/aws-record/record/table_migration.rb +6 -11
- data/lib/aws-record/record/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c99f94d8f0401d3de3c1886e58cc8af973cd5ec
|
4
|
+
data.tar.gz: b824eac6e13b8d37927ec34eb4cb24d39cf15063
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5e381404cc144a57792316da027c990f0d7b5600187e38afa9eb84c559fc1d0e896da300beee534f76eca4dbed21d90198db7b6740c3f261d2db5719a045865
|
7
|
+
data.tar.gz: 3c985a0bb11eed715c941f3138cc3195be3b34bad7b12f21d3e4ae0eccaf5de783015c4fab5bc099ea37c3e1bf64814c94b5644f9b8df8fc33a6661828ff496c
|
data/lib/aws-record.rb
CHANGED
@@ -22,7 +22,10 @@ module Aws
|
|
22
22
|
autoload :DirtyTracking, 'aws-record/record/dirty_tracking'
|
23
23
|
autoload :Errors, 'aws-record/record/errors'
|
24
24
|
autoload :ItemCollection, 'aws-record/record/item_collection'
|
25
|
+
autoload :ItemData, 'aws-record/record/item_data'
|
25
26
|
autoload :ItemOperations, 'aws-record/record/item_operations'
|
27
|
+
autoload :KeyAttributes, 'aws-record/record/key_attributes'
|
28
|
+
autoload :ModelAttributes, 'aws-record/record/model_attributes'
|
26
29
|
autoload :Query, 'aws-record/record/query'
|
27
30
|
autoload :SecondaryIndexes, 'aws-record/record/secondary_indexes'
|
28
31
|
autoload :TableMigration, 'aws-record/record/table_migration'
|
data/lib/aws-record/record.rb
CHANGED
@@ -204,6 +204,12 @@ module Aws
|
|
204
204
|
@track_mutations == false ? false : true
|
205
205
|
end
|
206
206
|
|
207
|
+
def model_valid?
|
208
|
+
if @keys.hash_key.nil?
|
209
|
+
raise Errors::InvalidModel.new("Table models must include a hash key")
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
207
213
|
private
|
208
214
|
def _user_agent(custom)
|
209
215
|
if custom
|
@@ -39,11 +39,6 @@ module Aws
|
|
39
39
|
# "M", "L". Optional if this attribute will never be used for a key or
|
40
40
|
# secondary index, but most convenience methods for setting attributes
|
41
41
|
# will provide this.
|
42
|
-
# @option options [Boolean] :mutation_tracking Optional attribute used to
|
43
|
-
# indicate whether mutations to values should be explicitly tracked when
|
44
|
-
# determining if a value is "dirty". Important for collection types
|
45
|
-
# which are often primarily modified by mutation of a single object
|
46
|
-
# reference. By default, is false.
|
47
42
|
# @option options [Boolean] :persist_nil Optional attribute used to
|
48
43
|
# indicate whether nil values should be persisted. If true, explicitly
|
49
44
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -56,7 +51,6 @@ module Aws
|
|
56
51
|
@database_name = options[:database_attribute_name] || name.to_s
|
57
52
|
@dynamodb_type = options[:dynamodb_type]
|
58
53
|
@marshaler = options[:marshaler] || DefaultMarshaler
|
59
|
-
@mutation_tracking = options[:mutation_tracking]
|
60
54
|
@persist_nil = options[:persist_nil]
|
61
55
|
dv = options[:default_value]
|
62
56
|
@default_value = type_cast(dv) unless dv.nil?
|
@@ -85,12 +79,6 @@ module Aws
|
|
85
79
|
@marshaler.serialize(cast_value)
|
86
80
|
end
|
87
81
|
|
88
|
-
# @return [Boolean] true if this attribute should do active mutation
|
89
|
-
# tracking, false otherwise. Default: false
|
90
|
-
def track_mutations?
|
91
|
-
@mutation_tracking ? true : false
|
92
|
-
end
|
93
|
-
|
94
82
|
# @return [Boolean] true if this attribute will actively persist nil
|
95
83
|
# values, false otherwise. Default: false
|
96
84
|
def persist_nil?
|
@@ -17,9 +17,9 @@ module Aws
|
|
17
17
|
|
18
18
|
def self.included(sub_class)
|
19
19
|
sub_class.extend(ClassMethods)
|
20
|
-
|
21
|
-
sub_class.instance_variable_set("@attributes",
|
22
|
-
sub_class.instance_variable_set("@
|
20
|
+
model_attributes = ModelAttributes.new(self)
|
21
|
+
sub_class.instance_variable_set("@attributes", model_attributes)
|
22
|
+
sub_class.instance_variable_set("@keys", KeyAttributes.new(model_attributes))
|
23
23
|
end
|
24
24
|
|
25
25
|
# @example Usage Example
|
@@ -40,7 +40,10 @@ module Aws
|
|
40
40
|
# attribute values you wish to set.
|
41
41
|
# @return [Aws::Record] An item instance for your model.
|
42
42
|
def initialize(attr_values = {})
|
43
|
-
|
43
|
+
opts = {
|
44
|
+
track_mutations: self.class.mutation_tracking_enabled?
|
45
|
+
}
|
46
|
+
@data = ItemData.new(self.class.attributes, opts)
|
44
47
|
attr_values.each do |attr_name, attr_value|
|
45
48
|
send("#{attr_name}=", attr_value)
|
46
49
|
end
|
@@ -50,23 +53,9 @@ module Aws
|
|
50
53
|
#
|
51
54
|
# @return [Hash] Map of attribute names to raw values.
|
52
55
|
def to_h
|
53
|
-
@data.
|
56
|
+
@data.hash_copy
|
54
57
|
end
|
55
58
|
|
56
|
-
private
|
57
|
-
|
58
|
-
# @private
|
59
|
-
def read_attribute(name, attribute)
|
60
|
-
raw = @data[name]
|
61
|
-
attribute.type_cast(raw)
|
62
|
-
end
|
63
|
-
|
64
|
-
# @private
|
65
|
-
def write_attribute(name, attribute, value)
|
66
|
-
@data[name] = value
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
59
|
module ClassMethods
|
71
60
|
|
72
61
|
# Define an attribute for your model, providing your own attribute type.
|
@@ -87,11 +76,6 @@ module Aws
|
|
87
76
|
# "M", "L". Optional if this attribute will never be used for a key or
|
88
77
|
# secondary index, but most convenience methods for setting attributes
|
89
78
|
# will provide this.
|
90
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
91
|
-
# indicate whether mutations to values should be explicitly tracked
|
92
|
-
# when determining if a value is "dirty". Important for collection
|
93
|
-
# types which are often primarily modified by mutation of a single
|
94
|
-
# object reference. By default, is false.
|
95
79
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
96
80
|
# indicate whether nil values should be persisted. If true, explicitly
|
97
81
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -104,21 +88,9 @@ module Aws
|
|
104
88
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
105
89
|
# the range key for the table.
|
106
90
|
def attr(name, marshaler, opts = {})
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
attribute = Attribute.new(name, opts)
|
111
|
-
|
112
|
-
storage_name = attribute.database_name
|
113
|
-
|
114
|
-
check_for_naming_collisions(name, storage_name)
|
115
|
-
check_if_reserved(name)
|
116
|
-
|
117
|
-
@attributes[name] = attribute
|
118
|
-
@storage_attributes[storage_name] = name
|
119
|
-
|
120
|
-
define_attr_methods(name, attribute)
|
121
|
-
key_attributes(name, opts)
|
91
|
+
@attributes.register_attribute(name, marshaler, opts)
|
92
|
+
_define_attr_methods(name)
|
93
|
+
_key_attributes(name, opts)
|
122
94
|
end
|
123
95
|
|
124
96
|
# Define a string-type attribute for your model.
|
@@ -130,11 +102,6 @@ module Aws
|
|
130
102
|
# the hash key for the table.
|
131
103
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
132
104
|
# the range key for the table.
|
133
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
134
|
-
# indicate if mutations to values should be explicitly tracked when
|
135
|
-
# determining if a value is "dirty". Important for collection types
|
136
|
-
# which are often primarily modified by mutation of a single object
|
137
|
-
# reference. By default, is false.
|
138
105
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
139
106
|
# indicate whether nil values should be persisted. If true, explicitly
|
140
107
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -156,11 +123,6 @@ module Aws
|
|
156
123
|
# the hash key for the table.
|
157
124
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
158
125
|
# the range key for the table.
|
159
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
160
|
-
# indicate if mutations to values should be explicitly tracked when
|
161
|
-
# determining if a value is "dirty". Important for collection types
|
162
|
-
# which are often primarily modified by mutation of a single object
|
163
|
-
# reference. By default, is false.
|
164
126
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
165
127
|
# indicate whether nil values should be persisted. If true, explicitly
|
166
128
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -182,11 +144,6 @@ module Aws
|
|
182
144
|
# the hash key for the table.
|
183
145
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
184
146
|
# the range key for the table.
|
185
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
186
|
-
# indicate if mutations to values should be explicitly tracked when
|
187
|
-
# determining if a value is "dirty". Important for collection types
|
188
|
-
# which are often primarily modified by mutation of a single object
|
189
|
-
# reference. By default, is false.
|
190
147
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
191
148
|
# indicate whether nil values should be persisted. If true, explicitly
|
192
149
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -208,11 +165,6 @@ module Aws
|
|
208
165
|
# the hash key for the table.
|
209
166
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
210
167
|
# the range key for the table.
|
211
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
212
|
-
# indicate if mutations to values should be explicitly tracked when
|
213
|
-
# determining if a value is "dirty". Important for collection types
|
214
|
-
# which are often primarily modified by mutation of a single object
|
215
|
-
# reference. By default, is false.
|
216
168
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
217
169
|
# indicate whether nil values should be persisted. If true, explicitly
|
218
170
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -234,11 +186,6 @@ module Aws
|
|
234
186
|
# the hash key for the table.
|
235
187
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
236
188
|
# the range key for the table.
|
237
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
238
|
-
# indicate if mutations to values should be explicitly tracked when
|
239
|
-
# determining if a value is "dirty". Important for collection types
|
240
|
-
# which are often primarily modified by mutation of a single object
|
241
|
-
# reference. By default, is false.
|
242
189
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
243
190
|
# indicate whether nil values should be persisted. If true, explicitly
|
244
191
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -260,11 +207,6 @@ module Aws
|
|
260
207
|
# the hash key for the table.
|
261
208
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
262
209
|
# the range key for the table.
|
263
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
264
|
-
# indicate if mutations to values should be explicitly tracked when
|
265
|
-
# determining if a value is "dirty". Important for collection types
|
266
|
-
# which are often primarily modified by mutation of a single object
|
267
|
-
# reference. By default, is false.
|
268
210
|
# @option opts [Boolean] :persist_nil Optional attribute used to
|
269
211
|
# indicate whether nil values should be persisted. If true, explicitly
|
270
212
|
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
@@ -304,17 +246,11 @@ module Aws
|
|
304
246
|
# the hash key for the table.
|
305
247
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
306
248
|
# the range key for the table.
|
307
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
308
|
-
# indicate if mutations to values should be explicitly tracked when
|
309
|
-
# determining if a value is "dirty". Important for collection types
|
310
|
-
# which are often primarily modified by mutation of a single object
|
311
|
-
# reference. By default, is true.
|
312
249
|
# @option opts [Object] :default_value Optional attribute used to
|
313
250
|
# define a "default value" to be used if the attribute's value on an
|
314
251
|
# item is nil or not set at persistence time.
|
315
252
|
def list_attr(name, opts = {})
|
316
253
|
opts[:dynamodb_type] = "L"
|
317
|
-
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
318
254
|
attr(name, Marshalers::ListMarshaler.new(opts), opts)
|
319
255
|
end
|
320
256
|
|
@@ -345,17 +281,11 @@ module Aws
|
|
345
281
|
# the hash key for the table.
|
346
282
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
347
283
|
# the range key for the table.
|
348
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
349
|
-
# indicate if mutations to values should be explicitly tracked when
|
350
|
-
# determining if a value is "dirty". Important for collection types
|
351
|
-
# which are often primarily modified by mutation of a single object
|
352
|
-
# reference. By default, is true.
|
353
284
|
# @option opts [Object] :default_value Optional attribute used to
|
354
285
|
# define a "default value" to be used if the attribute's value on an
|
355
286
|
# item is nil or not set at persistence time.
|
356
287
|
def map_attr(name, opts = {})
|
357
288
|
opts[:dynamodb_type] = "M"
|
358
|
-
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
359
289
|
attr(name, Marshalers::MapMarshaler.new(opts), opts)
|
360
290
|
end
|
361
291
|
|
@@ -376,17 +306,11 @@ module Aws
|
|
376
306
|
# the hash key for the table.
|
377
307
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
378
308
|
# the range key for the table.
|
379
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
380
|
-
# indicate if mutations to values should be explicitly tracked when
|
381
|
-
# determining if a value is "dirty". Important for collection types
|
382
|
-
# which are often primarily modified by mutation of a single object
|
383
|
-
# reference. By default, is true.
|
384
309
|
# @option opts [Object] :default_value Optional attribute used to
|
385
310
|
# define a "default value" to be used if the attribute's value on an
|
386
311
|
# item is nil or not set at persistence time.
|
387
312
|
def string_set_attr(name, opts = {})
|
388
313
|
opts[:dynamodb_type] = "SS"
|
389
|
-
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
390
314
|
attr(name, Marshalers::StringSetMarshaler.new(opts), opts)
|
391
315
|
end
|
392
316
|
|
@@ -407,118 +331,57 @@ module Aws
|
|
407
331
|
# the hash key for the table.
|
408
332
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
409
333
|
# the range key for the table.
|
410
|
-
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
411
|
-
# indicate if mutations to values should be explicitly tracked when
|
412
|
-
# determining if a value is "dirty". Important for collection types
|
413
|
-
# which are often primarily modified by mutation of a single object
|
414
|
-
# reference. By default, is true.
|
415
334
|
# @option opts [Object] :default_value Optional attribute used to
|
416
335
|
# define a "default value" to be used if the attribute's value on an
|
417
336
|
# item is nil or not set at persistence time.
|
418
337
|
def numeric_set_attr(name, opts = {})
|
419
338
|
opts[:dynamodb_type] = "NS"
|
420
|
-
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
421
339
|
attr(name, Marshalers::NumericSetMarshaler.new(opts), opts)
|
422
340
|
end
|
423
341
|
|
424
|
-
# @return [
|
425
|
-
def attributes
|
426
|
-
@attributes
|
427
|
-
end
|
428
|
-
|
429
|
-
# @return [Hash] hash of database names to attribute names
|
430
|
-
def storage_attributes
|
431
|
-
@storage_attributes
|
432
|
-
end
|
433
|
-
|
434
|
-
# @return [Aws::Record::Attribute,nil]
|
342
|
+
# @return [Symbol,nil]
|
435
343
|
def hash_key
|
436
|
-
@
|
344
|
+
@keys.hash_key
|
437
345
|
end
|
438
346
|
|
439
|
-
# @return [
|
347
|
+
# @return [Symbol,nil]
|
440
348
|
def range_key
|
441
|
-
@
|
349
|
+
@keys.range_key
|
442
350
|
end
|
443
351
|
|
444
|
-
# @
|
445
|
-
|
446
|
-
|
447
|
-
@keys
|
352
|
+
# @api private
|
353
|
+
def attributes
|
354
|
+
@attributes
|
448
355
|
end
|
449
356
|
|
450
|
-
# @
|
451
|
-
|
452
|
-
|
453
|
-
def track_mutations?(attr_sym)
|
454
|
-
mutation_tracking_enabled? && attributes[attr_sym].track_mutations?
|
357
|
+
# @api private
|
358
|
+
def keys
|
359
|
+
@keys.keys
|
455
360
|
end
|
456
361
|
|
457
362
|
private
|
458
|
-
def
|
363
|
+
def _define_attr_methods(name)
|
459
364
|
define_method(name) do
|
460
|
-
|
365
|
+
@data.get_attribute(name)
|
461
366
|
end
|
462
367
|
|
463
368
|
define_method("#{name}=") do |value|
|
464
|
-
|
369
|
+
@data.set_attribute(name, value)
|
465
370
|
end
|
466
371
|
end
|
467
372
|
|
468
|
-
def
|
373
|
+
def _key_attributes(id, opts)
|
469
374
|
if opts[:hash_key] == true && opts[:range_key] == true
|
470
375
|
raise ArgumentError.new(
|
471
376
|
"Cannot have the same attribute be a hash and range key."
|
472
377
|
)
|
473
378
|
elsif opts[:hash_key] == true
|
474
|
-
|
379
|
+
@keys.hash_key = id
|
475
380
|
elsif opts[:range_key] == true
|
476
|
-
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
|
-
def define_key(id, type)
|
481
|
-
@keys[type] = id
|
482
|
-
end
|
483
|
-
|
484
|
-
def validate_attr_name(name)
|
485
|
-
unless name.is_a?(Symbol)
|
486
|
-
raise ArgumentError.new("Must use symbolized :name attribute.")
|
487
|
-
end
|
488
|
-
if @attributes[name]
|
489
|
-
raise Errors::NameCollision.new(
|
490
|
-
"Cannot overwrite existing attribute #{name}"
|
491
|
-
)
|
381
|
+
@keys.range_key = id
|
492
382
|
end
|
493
383
|
end
|
494
384
|
|
495
|
-
def check_if_reserved(name)
|
496
|
-
if instance_methods.include?(name)
|
497
|
-
raise Errors::ReservedName.new(
|
498
|
-
"Cannot name an attribute #{name}, that would collide with an"\
|
499
|
-
" existing instance method."
|
500
|
-
)
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
def check_for_naming_collisions(name, storage_name)
|
505
|
-
if @attributes[storage_name.to_sym]
|
506
|
-
raise Errors::NameCollision.new(
|
507
|
-
"Custom storage name #{storage_name} already exists as an"\
|
508
|
-
" attribute name in #{@attributes}"
|
509
|
-
)
|
510
|
-
elsif @storage_attributes[name.to_s]
|
511
|
-
raise Errors::NameCollision.new(
|
512
|
-
"Attribute name #{name} already exists as a custom storage"\
|
513
|
-
" name in #{@storage_attributes}"
|
514
|
-
)
|
515
|
-
elsif @storage_attributes[storage_name]
|
516
|
-
raise Errors::NameCollision.new(
|
517
|
-
"Custom storage name #{storage_name} already in use in"\
|
518
|
-
" #{@storage_attributes}"
|
519
|
-
)
|
520
|
-
end
|
521
|
-
end
|
522
385
|
end
|
523
386
|
|
524
387
|
end
|
@@ -19,15 +19,6 @@ module Aws
|
|
19
19
|
sub_class.extend(DirtyTrackingClassMethods)
|
20
20
|
end
|
21
21
|
|
22
|
-
# @private
|
23
|
-
#
|
24
|
-
# @override initialize(*)
|
25
|
-
def initialize(*)
|
26
|
-
@dirty_data = {}
|
27
|
-
@mutation_copies = {}
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
22
|
# Returns +true+ if the specified attribute has any dirty changes, +false+ otherwise.
|
32
23
|
#
|
33
24
|
# @example
|
@@ -45,7 +36,7 @@ module Aws
|
|
45
36
|
# @param [String, Symbol] name The name of the attribute to to check for dirty changes.
|
46
37
|
# @return [Boolean] +true+ if the specified attribute has any dirty changes, +false+ otherwise.
|
47
38
|
def attribute_dirty?(name)
|
48
|
-
@
|
39
|
+
@data.attribute_dirty?(name)
|
49
40
|
end
|
50
41
|
|
51
42
|
# Returns the original value of the specified attribute.
|
@@ -64,11 +55,7 @@ module Aws
|
|
64
55
|
# @param [String, Symbol] name The name of the attribute to retrieve the original value of.
|
65
56
|
# @return [Object] The original value of the specified attribute.
|
66
57
|
def attribute_was(name)
|
67
|
-
|
68
|
-
@mutation_copies[name]
|
69
|
-
else
|
70
|
-
attribute_dirty?(name) ? @dirty_data[name] : @data[name]
|
71
|
-
end
|
58
|
+
@data.attribute_was(name)
|
72
59
|
end
|
73
60
|
|
74
61
|
# Mark that an attribute is changing. This is useful in situations where it is necessary to track that the value of an
|
@@ -106,44 +93,7 @@ module Aws
|
|
106
93
|
# @param [String, Symbol] name The name of the attribute to mark as
|
107
94
|
# changing.
|
108
95
|
def attribute_dirty!(name)
|
109
|
-
|
110
|
-
|
111
|
-
current_value = @data[name]
|
112
|
-
|
113
|
-
@dirty_data[name] =
|
114
|
-
begin
|
115
|
-
_deep_copy(current_value)
|
116
|
-
rescue TypeError
|
117
|
-
current_value
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# Marks the changes as applied by clearing the current changes and making
|
122
|
-
# them accessible through +previous_changes+.
|
123
|
-
#
|
124
|
-
# # @example
|
125
|
-
# class Model
|
126
|
-
# include Aws::Record
|
127
|
-
# integer_attr :id, hash_key: true
|
128
|
-
# string_attr :name
|
129
|
-
# end
|
130
|
-
#
|
131
|
-
# model.name # => 'Alex'
|
132
|
-
# model.name = 'Nick'
|
133
|
-
# model.dirty? # => true
|
134
|
-
#
|
135
|
-
# model.clean!
|
136
|
-
# model.dirty? # false
|
137
|
-
#
|
138
|
-
def clean!
|
139
|
-
@dirty_data.clear
|
140
|
-
self.class.attributes.each do |name, attribute|
|
141
|
-
if self.class.track_mutations?(name)
|
142
|
-
if @data[name]
|
143
|
-
@mutation_copies[name] = _deep_copy(@data[name])
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
96
|
+
@data.attribute_dirty!(name)
|
147
97
|
end
|
148
98
|
|
149
99
|
# Returns an array with the name of the attributes with dirty changes.
|
@@ -162,13 +112,7 @@ module Aws
|
|
162
112
|
#
|
163
113
|
# @return [Array] The names of attributes with dirty changes.
|
164
114
|
def dirty
|
165
|
-
|
166
|
-
@mutation_copies.each do |key, value|
|
167
|
-
if @data[key] != value
|
168
|
-
ret << key unless ret.include?(key)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
ret
|
115
|
+
@data.dirty
|
172
116
|
end
|
173
117
|
|
174
118
|
# Returns +true+ if any attributes have dirty changes, +false+ otherwise.
|
@@ -188,10 +132,7 @@ module Aws
|
|
188
132
|
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
189
133
|
# otherwise.
|
190
134
|
def dirty?
|
191
|
-
|
192
|
-
@mutation_copies.any? do |name, value|
|
193
|
-
@mutation_copies[name] != @data[name]
|
194
|
-
end
|
135
|
+
@data.dirty?
|
195
136
|
end
|
196
137
|
|
197
138
|
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
@@ -236,14 +177,7 @@ module Aws
|
|
236
177
|
#
|
237
178
|
# @param [String, Symbol] name The name of the attribute to restore
|
238
179
|
def rollback_attribute!(name)
|
239
|
-
|
240
|
-
|
241
|
-
if @mutation_copies.has_key?(name)
|
242
|
-
@data[name] = @mutation_copies[name]
|
243
|
-
@dirty_data.delete(name) if @dirty_data.has_key?(name)
|
244
|
-
else
|
245
|
-
@data[name] = @dirty_data.delete(name)
|
246
|
-
end
|
180
|
+
@data.rollback_attribute!(name)
|
247
181
|
end
|
248
182
|
|
249
183
|
# Restores all attributes to their original values.
|
@@ -265,6 +199,11 @@ module Aws
|
|
265
199
|
Array(names).each { |name| rollback_attribute!(name) }
|
266
200
|
end
|
267
201
|
|
202
|
+
# @api private
|
203
|
+
def clean!
|
204
|
+
@data.clean!
|
205
|
+
end
|
206
|
+
|
268
207
|
# @private
|
269
208
|
#
|
270
209
|
# @override save(*)
|
@@ -272,36 +211,6 @@ module Aws
|
|
272
211
|
super.tap { clean! }
|
273
212
|
end
|
274
213
|
|
275
|
-
private
|
276
|
-
|
277
|
-
# @private
|
278
|
-
#
|
279
|
-
# @override write_attribute(*)
|
280
|
-
def write_attribute(name, attribute, value)
|
281
|
-
_dirty_write_attribute(name, attribute, value)
|
282
|
-
super
|
283
|
-
end
|
284
|
-
|
285
|
-
def _dirty_write_attribute(name, attribute, value)
|
286
|
-
if value == attribute_was(name)
|
287
|
-
@dirty_data.delete(name)
|
288
|
-
else
|
289
|
-
attribute_dirty!(name)
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def _mutated?(name)
|
294
|
-
if @mutation_copies.has_key?(name)
|
295
|
-
@data[name] != @mutation_copies[name]
|
296
|
-
else
|
297
|
-
false
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
def _deep_copy(obj)
|
302
|
-
Marshal.load(Marshal.dump(obj))
|
303
|
-
end
|
304
|
-
|
305
214
|
module DirtyTrackingClassMethods
|
306
215
|
|
307
216
|
private
|
@@ -316,7 +225,7 @@ module Aws
|
|
316
225
|
# @private
|
317
226
|
#
|
318
227
|
# @override define_attr_methods(*)
|
319
|
-
def
|
228
|
+
def _define_attr_methods(name)
|
320
229
|
super.tap do
|
321
230
|
define_method("#{name}_dirty?") do
|
322
231
|
attribute_dirty?(name)
|
@@ -43,9 +43,10 @@ module Aws
|
|
43
43
|
items.each do |item|
|
44
44
|
record = model.new
|
45
45
|
data = record.instance_variable_get("@data")
|
46
|
-
model.attributes.each do |name, attr|
|
47
|
-
data
|
46
|
+
model.attributes.attributes.each do |name, attr|
|
47
|
+
data.set_attribute(name, attr.extract(item))
|
48
48
|
end
|
49
|
+
data.clean!
|
49
50
|
ret << record
|
50
51
|
end
|
51
52
|
ret
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
14
|
+
module Aws
|
15
|
+
module Record
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
class ItemData
|
19
|
+
def initialize(model_attributes, opts)
|
20
|
+
@data = {}
|
21
|
+
@clean_copies = {}
|
22
|
+
@dirty_flags = {}
|
23
|
+
@model_attributes = model_attributes
|
24
|
+
@track_mutations = opts[:track_mutations]
|
25
|
+
@track_mutations = true if opts[:track_mutations].nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_attribute(name)
|
29
|
+
@model_attributes.attribute_for(name).type_cast(@data[name])
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_attribute(name, value)
|
33
|
+
@data[name] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def raw_value(name)
|
37
|
+
@data[name]
|
38
|
+
end
|
39
|
+
|
40
|
+
def clean!
|
41
|
+
@dirty_flags = {}
|
42
|
+
@model_attributes.attributes.each_key do |name|
|
43
|
+
populate_default_values
|
44
|
+
value = get_attribute(name)
|
45
|
+
if @track_mutations
|
46
|
+
@clean_copies[name] = _deep_copy(value)
|
47
|
+
else
|
48
|
+
@clean_copies[name] = value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def attribute_dirty?(name)
|
54
|
+
if @dirty_flags[name]
|
55
|
+
true
|
56
|
+
else
|
57
|
+
value = get_attribute(name)
|
58
|
+
value != @clean_copies[name]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def attribute_was(name)
|
63
|
+
@clean_copies[name]
|
64
|
+
end
|
65
|
+
|
66
|
+
def attribute_dirty!(name)
|
67
|
+
@dirty_flags[name] = true
|
68
|
+
end
|
69
|
+
|
70
|
+
def dirty
|
71
|
+
@model_attributes.attributes.keys.inject([]) do |acc, name|
|
72
|
+
acc << name if attribute_dirty?(name)
|
73
|
+
acc
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def dirty?
|
78
|
+
dirty.empty? ? false : true
|
79
|
+
end
|
80
|
+
|
81
|
+
def rollback_attribute!(name)
|
82
|
+
if attribute_dirty?(name)
|
83
|
+
@dirty_flags.delete(name)
|
84
|
+
set_attribute(name, attribute_was(name))
|
85
|
+
end
|
86
|
+
get_attribute(name)
|
87
|
+
end
|
88
|
+
|
89
|
+
def hash_copy
|
90
|
+
@data.dup
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_save_hash
|
94
|
+
@data.inject({}) do |acc, name_value_pair|
|
95
|
+
attr_name, raw_value = name_value_pair
|
96
|
+
attribute = @model_attributes.attribute_for(attr_name)
|
97
|
+
if !raw_value.nil? || attribute.persist_nil?
|
98
|
+
db_name = attribute.database_name
|
99
|
+
acc[db_name] = attribute.serialize(raw_value)
|
100
|
+
end
|
101
|
+
acc
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def populate_default_values
|
106
|
+
@model_attributes.attributes.each do |name, attribute|
|
107
|
+
unless attribute.default_value.nil?
|
108
|
+
if @data[name].nil? && @data[name].nil?
|
109
|
+
@data[name] = attribute.default_value
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def _deep_copy(obj)
|
117
|
+
Marshal.load(Marshal.dump(obj))
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -154,33 +154,17 @@ module Aws
|
|
154
154
|
|
155
155
|
def _build_item_for_save
|
156
156
|
validate_key_values
|
157
|
-
|
158
|
-
|
159
|
-
@data.inject({}) do |acc, name_value_pair|
|
160
|
-
attr_name, raw_value = name_value_pair
|
161
|
-
attribute = attributes[attr_name]
|
162
|
-
if !raw_value.nil? || attribute.persist_nil?
|
163
|
-
db_name = attribute.database_name
|
164
|
-
acc[db_name] = attribute.serialize(raw_value)
|
165
|
-
end
|
166
|
-
acc
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def _populate_default_values(attributes)
|
171
|
-
attributes.each do |attr_name, attribute|
|
172
|
-
if !attribute.default_value.nil? && @data[attribute.name].nil?
|
173
|
-
@data[attr_name] = attribute.default_value
|
174
|
-
end
|
175
|
-
end
|
157
|
+
@data.populate_default_values
|
158
|
+
@data.build_save_hash
|
176
159
|
end
|
177
160
|
|
178
161
|
def key_values
|
179
162
|
validate_key_values
|
180
163
|
attributes = self.class.attributes
|
181
164
|
self.class.keys.inject({}) do |acc, (_, attr_name)|
|
182
|
-
db_name = attributes
|
183
|
-
acc[db_name] = attributes
|
165
|
+
db_name = attributes.storage_name_for(attr_name)
|
166
|
+
acc[db_name] = attributes.attribute_for(attr_name).
|
167
|
+
serialize(@data.raw_value(attr_name))
|
184
168
|
acc
|
185
169
|
end
|
186
170
|
end
|
@@ -196,7 +180,7 @@ module Aws
|
|
196
180
|
|
197
181
|
def missing_key_values
|
198
182
|
self.class.keys.inject([]) do |acc, key|
|
199
|
-
acc << key.last if @data
|
183
|
+
acc << key.last if @data.raw_value(key.last).nil?
|
200
184
|
acc
|
201
185
|
end
|
202
186
|
end
|
@@ -211,13 +195,14 @@ module Aws
|
|
211
195
|
def prevent_overwrite_expression
|
212
196
|
conditions = []
|
213
197
|
expression_attribute_names = {}
|
198
|
+
keys = self.class.instance_variable_get("@keys")
|
214
199
|
# Hash Key
|
215
200
|
conditions << "attribute_not_exists(#H)"
|
216
|
-
expression_attribute_names["#H"] =
|
201
|
+
expression_attribute_names["#H"] = keys.hash_key_attribute.database_name
|
217
202
|
# Range Key
|
218
203
|
if self.class.range_key
|
219
204
|
conditions << "attribute_not_exists(#R)"
|
220
|
-
expression_attribute_names["#R"] =
|
205
|
+
expression_attribute_names["#R"] = keys.range_key_attribute.database_name
|
221
206
|
end
|
222
207
|
{
|
223
208
|
condition_expression: conditions.join(" and "),
|
@@ -228,7 +213,7 @@ module Aws
|
|
228
213
|
def _dirty_changes_for_update
|
229
214
|
attributes = self.class.attributes
|
230
215
|
ret = dirty.inject({}) do |acc, attr_name|
|
231
|
-
acc[attr_name] = @data
|
216
|
+
acc[attr_name] = @data.raw_value(attr_name)
|
232
217
|
acc
|
233
218
|
end
|
234
219
|
ret
|
@@ -252,14 +237,15 @@ module Aws
|
|
252
237
|
# not include all table keys.
|
253
238
|
def find(opts)
|
254
239
|
key = {}
|
255
|
-
@keys.each_value do |attr_sym|
|
240
|
+
@keys.keys.each_value do |attr_sym|
|
256
241
|
unless opts[attr_sym]
|
257
242
|
raise Errors::KeyMissing.new(
|
258
243
|
"Missing required key #{attr_sym} in #{opts}"
|
259
244
|
)
|
260
245
|
end
|
261
|
-
attr_name = attributes
|
262
|
-
key[attr_name] = attributes
|
246
|
+
attr_name = attributes.storage_name_for(attr_sym)
|
247
|
+
key[attr_name] = attributes.attribute_for(attr_sym).
|
248
|
+
serialize(opts[attr_sym])
|
263
249
|
end
|
264
250
|
request_opts = {
|
265
251
|
table_name: table_name,
|
@@ -298,14 +284,14 @@ module Aws
|
|
298
284
|
def update(opts)
|
299
285
|
key = {}
|
300
286
|
updates = {}
|
301
|
-
@keys.each_value do |attr_sym|
|
287
|
+
@keys.keys.each_value do |attr_sym|
|
302
288
|
unless value = opts.delete(attr_sym)
|
303
289
|
raise Errors::KeyMissing.new(
|
304
290
|
"Missing required key #{attr_sym} in #{opts}"
|
305
291
|
)
|
306
292
|
end
|
307
|
-
attr_name = attributes
|
308
|
-
key[attr_name] = attributes
|
293
|
+
attr_name = attributes.storage_name_for(attr_sym)
|
294
|
+
key[attr_name] = attributes.attribute_for(attr_sym).serialize(value)
|
309
295
|
end
|
310
296
|
request_opts = {
|
311
297
|
table_name: table_name,
|
@@ -335,8 +321,8 @@ module Aws
|
|
335
321
|
name_sub_token = name_sub_token.succ
|
336
322
|
value_sub_token = value_sub_token.succ
|
337
323
|
|
338
|
-
attribute = attributes
|
339
|
-
attr_name =
|
324
|
+
attribute = attributes.attribute_for(attr_sym)
|
325
|
+
attr_name = attributes.storage_name_for(attr_sym)
|
340
326
|
exp_attr_names[name_sub] = attr_name
|
341
327
|
if _update_type_remove?(attribute, value)
|
342
328
|
remove_expressions << "#{name_sub}"
|
@@ -362,8 +348,8 @@ module Aws
|
|
362
348
|
def build_item_from_resp(resp)
|
363
349
|
record = new
|
364
350
|
data = record.instance_variable_get("@data")
|
365
|
-
attributes.each do |name, attr|
|
366
|
-
data
|
351
|
+
attributes.attributes.each do |name, attr|
|
352
|
+
data.set_attribute(name, attr.extract(resp.item))
|
367
353
|
end
|
368
354
|
record
|
369
355
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
14
|
+
module Aws
|
15
|
+
module Record
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
class KeyAttributes
|
19
|
+
attr_reader :keys
|
20
|
+
|
21
|
+
def initialize(model_attributes)
|
22
|
+
@keys = {}
|
23
|
+
@model_attributes = model_attributes
|
24
|
+
end
|
25
|
+
|
26
|
+
def hash_key
|
27
|
+
@hash_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def hash_key_attribute
|
31
|
+
@model_attributes.attribute_for(hash_key)
|
32
|
+
end
|
33
|
+
|
34
|
+
def range_key
|
35
|
+
@range_key
|
36
|
+
end
|
37
|
+
|
38
|
+
def range_key_attribute
|
39
|
+
@model_attributes.attribute_for(range_key)
|
40
|
+
end
|
41
|
+
|
42
|
+
def hash_key=(value)
|
43
|
+
@keys[:hash] = value
|
44
|
+
@hash_key = value
|
45
|
+
end
|
46
|
+
|
47
|
+
def range_key=(value)
|
48
|
+
@keys[:range] = value
|
49
|
+
@range_key = value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
14
|
+
module Aws
|
15
|
+
module Record
|
16
|
+
|
17
|
+
# @api private
|
18
|
+
class ModelAttributes
|
19
|
+
attr_reader :attributes, :storage_attributes
|
20
|
+
|
21
|
+
def initialize(model_class)
|
22
|
+
@model_class = model_class
|
23
|
+
@attributes = {}
|
24
|
+
@storage_attributes = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def register_attribute(name, marshaler, opts)
|
28
|
+
attribute = Attribute.new(name, opts.merge(marshaler: marshaler))
|
29
|
+
_new_attr_validation(name, attribute)
|
30
|
+
@attributes[name] = attribute
|
31
|
+
@storage_attributes[attribute.database_name] = name
|
32
|
+
attribute
|
33
|
+
end
|
34
|
+
|
35
|
+
def attribute_for(name)
|
36
|
+
@attributes[name]
|
37
|
+
end
|
38
|
+
|
39
|
+
def storage_name_for(name)
|
40
|
+
attribute_for(name).database_name
|
41
|
+
end
|
42
|
+
|
43
|
+
def present?(name)
|
44
|
+
attribute_for(name) ? true : false
|
45
|
+
end
|
46
|
+
|
47
|
+
def db_to_attribute_name(storage_name)
|
48
|
+
@storage_attributes[storage_name]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def _new_attr_validation(name, attribute)
|
53
|
+
_validate_attr_name(name)
|
54
|
+
_check_for_naming_collisions(name, attribute.database_name)
|
55
|
+
_check_if_reserved(name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def _validate_attr_name(name)
|
59
|
+
unless name.is_a?(Symbol)
|
60
|
+
raise ArgumentError.new("Must use symbolized :name attribute.")
|
61
|
+
end
|
62
|
+
if @attributes[name]
|
63
|
+
raise Errors::NameCollision.new(
|
64
|
+
"Cannot overwrite existing attribute #{name}"
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def _check_if_reserved(name)
|
70
|
+
if @model_class.instance_methods.include?(name)
|
71
|
+
raise Errors::ReservedName.new(
|
72
|
+
"Cannot name an attribute #{name}, that would collide with an"\
|
73
|
+
" existing instance method."
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def _check_for_naming_collisions(name, storage_name)
|
79
|
+
if @attributes[storage_name.to_sym]
|
80
|
+
raise Errors::NameCollision.new(
|
81
|
+
"Custom storage name #{storage_name} already exists as an"\
|
82
|
+
" attribute name in #{@attributes}"
|
83
|
+
)
|
84
|
+
elsif @storage_attributes[name.to_s]
|
85
|
+
raise Errors::NameCollision.new(
|
86
|
+
"Attribute name #{name} already exists as a custom storage"\
|
87
|
+
" name in #{@storage_attributes}"
|
88
|
+
)
|
89
|
+
elsif @storage_attributes[storage_name]
|
90
|
+
raise Errors::NameCollision.new(
|
91
|
+
"Custom storage name #{storage_name} already in use in"\
|
92
|
+
" #{@storage_attributes}"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -37,7 +37,7 @@ module Aws
|
|
37
37
|
# are copied from the table to the index. See shape details in the
|
38
38
|
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Types/Projection.html AWS SDK for Ruby V2 docs}.
|
39
39
|
def local_secondary_index(name, opts)
|
40
|
-
opts[:hash_key] = hash_key
|
40
|
+
opts[:hash_key] = hash_key
|
41
41
|
_validate_required_lsi_keys(opts)
|
42
42
|
local_secondary_indexes[name] = opts
|
43
43
|
end
|
@@ -102,12 +102,12 @@ module Aws
|
|
102
102
|
def _si_key_schema(opts)
|
103
103
|
key_schema = [{
|
104
104
|
key_type: "HASH",
|
105
|
-
attribute_name: @attributes
|
105
|
+
attribute_name: @attributes.storage_name_for(opts[:hash_key])
|
106
106
|
}]
|
107
107
|
if opts[:range_key]
|
108
108
|
key_schema << {
|
109
109
|
key_type: "RANGE",
|
110
|
-
attribute_name: @attributes
|
110
|
+
attribute_name: @attributes.storage_name_for(opts[:range_key])
|
111
111
|
}
|
112
112
|
end
|
113
113
|
key_schema
|
@@ -139,13 +139,13 @@ module Aws
|
|
139
139
|
|
140
140
|
def _validate_attributes_exist(*attr_names)
|
141
141
|
missing = attr_names.select do |attr_name|
|
142
|
-
|
142
|
+
!@attributes.present?(attr_name)
|
143
143
|
end
|
144
144
|
unless missing.empty?
|
145
145
|
raise ArgumentError.new(
|
146
146
|
"#{missing.join(", ")} not present in model attributes."\
|
147
147
|
" Please ensure that attributes are defined in the model"\
|
148
|
-
" class BEFORE defining
|
148
|
+
" class BEFORE defining an index on those attributes."
|
149
149
|
)
|
150
150
|
end
|
151
151
|
end
|
@@ -133,7 +133,7 @@ module Aws
|
|
133
133
|
private
|
134
134
|
def _assert_model_valid(model)
|
135
135
|
_assert_required_include(model)
|
136
|
-
|
136
|
+
model.model_valid?
|
137
137
|
end
|
138
138
|
|
139
139
|
def _assert_required_include(model)
|
@@ -142,12 +142,6 @@ module Aws
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
-
def _assert_keys(model)
|
146
|
-
if model.hash_key.nil?
|
147
|
-
raise Errors::InvalidModel.new("Table models must include a hash key")
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
145
|
def _attribute_definitions
|
152
146
|
_keys.map do |type, attr|
|
153
147
|
{
|
@@ -158,6 +152,7 @@ module Aws
|
|
158
152
|
end
|
159
153
|
|
160
154
|
def _append_to_attribute_definitions(secondary_indexes, create_opts)
|
155
|
+
attributes = @model.attributes
|
161
156
|
attr_def = create_opts[:attribute_definitions]
|
162
157
|
secondary_indexes.each do |si|
|
163
158
|
si[:key_schema].each do |key_schema|
|
@@ -165,9 +160,9 @@ module Aws
|
|
165
160
|
a[:attribute_name] == key_schema[:attribute_name]
|
166
161
|
}
|
167
162
|
unless exists
|
168
|
-
attr =
|
169
|
-
|
170
|
-
|
163
|
+
attr = attributes.attribute_for(
|
164
|
+
attributes.db_to_attribute_name(key_schema[:attribute_name])
|
165
|
+
)
|
171
166
|
attr_def << {
|
172
167
|
attribute_name: attr.database_name,
|
173
168
|
attribute_type: attr.dynamodb_type
|
@@ -208,7 +203,7 @@ module Aws
|
|
208
203
|
|
209
204
|
def _keys
|
210
205
|
@model.keys.inject({}) do |acc, (type, name)|
|
211
|
-
acc[type] = @model.attributes
|
206
|
+
acc[type] = @model.attributes.attribute_for(name)
|
212
207
|
acc
|
213
208
|
end
|
214
209
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws-record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-resources
|
@@ -38,7 +38,9 @@ files:
|
|
38
38
|
- lib/aws-record/record/dirty_tracking.rb
|
39
39
|
- lib/aws-record/record/errors.rb
|
40
40
|
- lib/aws-record/record/item_collection.rb
|
41
|
+
- lib/aws-record/record/item_data.rb
|
41
42
|
- lib/aws-record/record/item_operations.rb
|
43
|
+
- lib/aws-record/record/key_attributes.rb
|
42
44
|
- lib/aws-record/record/marshalers/boolean_marshaler.rb
|
43
45
|
- lib/aws-record/record/marshalers/date_marshaler.rb
|
44
46
|
- lib/aws-record/record/marshalers/date_time_marshaler.rb
|
@@ -49,6 +51,7 @@ files:
|
|
49
51
|
- lib/aws-record/record/marshalers/numeric_set_marshaler.rb
|
50
52
|
- lib/aws-record/record/marshalers/string_marshaler.rb
|
51
53
|
- lib/aws-record/record/marshalers/string_set_marshaler.rb
|
54
|
+
- lib/aws-record/record/model_attributes.rb
|
52
55
|
- lib/aws-record/record/query.rb
|
53
56
|
- lib/aws-record/record/secondary_indexes.rb
|
54
57
|
- lib/aws-record/record/table_migration.rb
|