aws-record 2.10.1 → 2.11.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/lib/aws-record/record/attribute.rb +4 -6
- data/lib/aws-record/record/attributes.rb +36 -49
- data/lib/aws-record/record/batch.rb +13 -12
- data/lib/aws-record/record/batch_read.rb +5 -2
- data/lib/aws-record/record/buildable_search.rb +29 -26
- data/lib/aws-record/record/client_configuration.rb +9 -9
- data/lib/aws-record/record/dirty_tracking.rb +29 -32
- data/lib/aws-record/record/errors.rb +0 -1
- data/lib/aws-record/record/item_collection.rb +4 -4
- data/lib/aws-record/record/item_data.rb +3 -6
- data/lib/aws-record/record/item_operations.rb +77 -93
- data/lib/aws-record/record/key_attributes.rb +0 -2
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/date_marshaler.rb +0 -3
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +1 -2
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +0 -2
- data/lib/aws-record/record/marshalers/float_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/list_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/map_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/string_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/time_marshaler.rb +0 -2
- data/lib/aws-record/record/model_attributes.rb +13 -23
- data/lib/aws-record/record/query.rb +6 -9
- data/lib/aws-record/record/secondary_indexes.rb +22 -30
- data/lib/aws-record/record/table_config.rb +51 -62
- data/lib/aws-record/record/table_migration.rb +42 -54
- data/lib/aws-record/record/transactions.rb +32 -35
- data/lib/aws-record/record.rb +29 -37
- metadata +11 -5
@@ -3,7 +3,6 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module DirtyTracking
|
6
|
-
|
7
6
|
def self.included(sub_class)
|
8
7
|
sub_class.extend(DirtyTrackingClassMethods)
|
9
8
|
end
|
@@ -26,7 +25,7 @@ module Aws
|
|
26
25
|
# @return [Boolean] +true+ if the specified attribute has any dirty changes, +false+ otherwise.
|
27
26
|
def attribute_dirty?(name)
|
28
27
|
@data.attribute_dirty?(name)
|
29
|
-
end
|
28
|
+
end
|
30
29
|
|
31
30
|
# Returns the original value of the specified attribute.
|
32
31
|
#
|
@@ -39,7 +38,7 @@ module Aws
|
|
39
38
|
#
|
40
39
|
# model.name # => 'Alex'
|
41
40
|
# model.name = 'Nick'
|
42
|
-
# model.name_was # => 'Alex'
|
41
|
+
# model.name_was # => 'Alex'
|
43
42
|
#
|
44
43
|
# @param [String, Symbol] name The name of the attribute to retrieve the original value of.
|
45
44
|
# @return [Object] The original value of the specified attribute.
|
@@ -47,8 +46,9 @@ module Aws
|
|
47
46
|
@data.attribute_was(name)
|
48
47
|
end
|
49
48
|
|
50
|
-
# Mark that an attribute is changing. This is useful in situations
|
51
|
-
#
|
49
|
+
# Mark that an attribute is changing. This is useful in situations
|
50
|
+
# where it is necessary to track that the value of an
|
51
|
+
# attribute is changing in-place.
|
52
52
|
#
|
53
53
|
# @example
|
54
54
|
# class Model
|
@@ -63,9 +63,9 @@ module Aws
|
|
63
63
|
#
|
64
64
|
# model.name << 'i'
|
65
65
|
# model.name # => 'Alexi'
|
66
|
-
#
|
67
|
-
# # The change was made in place. Since the String instance representing
|
68
|
-
# # the value of name is the same as it was originally, the change is not
|
66
|
+
#
|
67
|
+
# # The change was made in place. Since the String instance representing
|
68
|
+
# # the value of name is the same as it was originally, the change is not
|
69
69
|
# # detected.
|
70
70
|
# model.name_dirty? # => false
|
71
71
|
# model.name_was # => 'Alexi'
|
@@ -79,7 +79,7 @@ module Aws
|
|
79
79
|
# model.name_dirty? # => true
|
80
80
|
# model.name_was # => 'Alexi'
|
81
81
|
#
|
82
|
-
# @param [String, Symbol] name The name of the attribute to mark as
|
82
|
+
# @param [String, Symbol] name The name of the attribute to mark as
|
83
83
|
# changing.
|
84
84
|
def attribute_dirty!(name)
|
85
85
|
@data.attribute_dirty!(name)
|
@@ -118,7 +118,7 @@ module Aws
|
|
118
118
|
# model.name = 'Nick'
|
119
119
|
# model.dirty? # => true
|
120
120
|
#
|
121
|
-
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
121
|
+
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
122
122
|
# otherwise.
|
123
123
|
def dirty?
|
124
124
|
@data.dirty?
|
@@ -140,7 +140,7 @@ module Aws
|
|
140
140
|
# model.delete!
|
141
141
|
# model.persisted? # => false
|
142
142
|
#
|
143
|
-
# @return [Boolean] +true+ if the model is not new and has not been deleted, +false+
|
143
|
+
# @return [Boolean] +true+ if the model is not new and has not been deleted, +false+
|
144
144
|
# otherwise.
|
145
145
|
def persisted?
|
146
146
|
@data.persisted?
|
@@ -160,7 +160,7 @@ module Aws
|
|
160
160
|
# model.save
|
161
161
|
# model.new_record? # => false
|
162
162
|
#
|
163
|
-
# @return [Boolean] +true+ if the model is newly initialized, +false+
|
163
|
+
# @return [Boolean] +true+ if the model is newly initialized, +false+
|
164
164
|
# otherwise.
|
165
165
|
def new_record?
|
166
166
|
@data.new_record?
|
@@ -179,34 +179,34 @@ module Aws
|
|
179
179
|
# model.destroyed? # => false
|
180
180
|
# model.save
|
181
181
|
# model.destroyed? # => false
|
182
|
-
# model.delete!
|
182
|
+
# model.delete!
|
183
183
|
# model.destroyed? # => true
|
184
184
|
#
|
185
|
-
# @return [Boolean] +true+ if the model has been destroyed, +false+
|
185
|
+
# @return [Boolean] +true+ if the model has been destroyed, +false+
|
186
186
|
# otherwise.
|
187
187
|
def destroyed?
|
188
188
|
@data.destroyed?
|
189
189
|
end
|
190
190
|
|
191
|
-
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
191
|
+
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
192
192
|
# using its primary key and the +find(*)+ class method.
|
193
193
|
#
|
194
|
-
# @raise [Aws::Record::Errors::NotFound] if no record exists in the
|
194
|
+
# @raise [Aws::Record::Errors::NotFound] if no record exists in the
|
195
195
|
# database matching the primary key of the item instance.
|
196
|
-
|
196
|
+
|
197
197
|
# @return [self] Returns the item instance.
|
198
198
|
def reload!
|
199
|
-
primary_key = self.class.keys.values.
|
199
|
+
primary_key = self.class.keys.values.each_with_object({}) do |key, memo|
|
200
200
|
memo[key] = send(key)
|
201
|
-
memo
|
201
|
+
memo
|
202
202
|
end
|
203
203
|
|
204
204
|
record = self.class.find(primary_key)
|
205
205
|
|
206
|
-
|
207
|
-
@data = record.instance_variable_get(
|
206
|
+
if record.present?
|
207
|
+
@data = record.instance_variable_get('@data')
|
208
208
|
else
|
209
|
-
raise Errors::NotFound
|
209
|
+
raise Errors::NotFound, 'No record found'
|
210
210
|
end
|
211
211
|
|
212
212
|
clean!
|
@@ -247,7 +247,7 @@ module Aws
|
|
247
247
|
# model.rollback!
|
248
248
|
# model.name # => 'Alex'
|
249
249
|
#
|
250
|
-
# @param [Array, String, Symbol] names The names of attributes to restore.
|
250
|
+
# @param [Array, String, Symbol] names The names of attributes to restore.
|
251
251
|
def rollback!(names = dirty)
|
252
252
|
Array(names).each { |name| rollback_attribute!(name) }
|
253
253
|
end
|
@@ -265,41 +265,38 @@ module Aws
|
|
265
265
|
end
|
266
266
|
|
267
267
|
module DirtyTrackingClassMethods
|
268
|
-
|
269
268
|
private
|
270
269
|
|
271
270
|
# @private
|
272
271
|
#
|
273
272
|
# @override build_item_from_resp(*)
|
274
273
|
def build_item_from_resp(*)
|
275
|
-
super.tap
|
274
|
+
super.tap(&:clean!)
|
276
275
|
end
|
277
276
|
|
278
277
|
# @private
|
279
278
|
#
|
280
279
|
# @override define_attr_methods(*)
|
281
280
|
def _define_attr_methods(name)
|
282
|
-
super.tap do
|
283
|
-
define_method("#{name}_dirty?") do
|
281
|
+
super.tap do
|
282
|
+
define_method("#{name}_dirty?") do
|
284
283
|
attribute_dirty?(name)
|
285
284
|
end
|
286
285
|
|
287
|
-
define_method("#{name}_dirty!") do
|
286
|
+
define_method("#{name}_dirty!") do
|
288
287
|
attribute_dirty!(name)
|
289
288
|
end
|
290
289
|
|
291
|
-
define_method("#{name}_was") do
|
290
|
+
define_method("#{name}_was") do
|
292
291
|
attribute_was(name)
|
293
292
|
end
|
294
293
|
|
295
|
-
define_method("rollback_#{name}!") do
|
294
|
+
define_method("rollback_#{name}!") do
|
296
295
|
rollback_attribute!(name)
|
297
296
|
end
|
298
297
|
end
|
299
298
|
end
|
300
|
-
|
301
299
|
end
|
302
|
-
|
303
300
|
end
|
304
301
|
end
|
305
302
|
end
|
@@ -25,7 +25,7 @@ module Aws
|
|
25
25
|
# @return [Enumerable<Aws::Record>] an enumeration over the results of
|
26
26
|
# your query or scan request. These results are automatically converted
|
27
27
|
# into items on your behalf.
|
28
|
-
def each
|
28
|
+
def each
|
29
29
|
return enum_for(:each) unless block_given?
|
30
30
|
items.each_page do |page|
|
31
31
|
@last_evaluated_key = page.last_evaluated_key
|
@@ -72,19 +72,20 @@ module Aws
|
|
72
72
|
# otherwise.
|
73
73
|
def empty?
|
74
74
|
items.each_page do |page|
|
75
|
-
return false
|
75
|
+
return false unless page.items.empty?
|
76
76
|
end
|
77
77
|
true
|
78
78
|
end
|
79
79
|
|
80
80
|
private
|
81
|
+
|
81
82
|
def _build_items_from_response(items, model)
|
82
83
|
ret = []
|
83
84
|
items.each do |item|
|
84
85
|
model_class = @model_filter ? @model_filter.call(item) : model
|
85
86
|
next unless model_class
|
86
87
|
record = model_class.new
|
87
|
-
data = record.instance_variable_get(
|
88
|
+
data = record.instance_variable_get('@data')
|
88
89
|
model_class.attributes.attributes.each do |name, attr|
|
89
90
|
data.set_attribute(name, attr.extract(item))
|
90
91
|
end
|
@@ -98,7 +99,6 @@ module Aws
|
|
98
99
|
def items
|
99
100
|
@_items ||= @client.send(@search_method, @search_params)
|
100
101
|
end
|
101
|
-
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
|
-
|
6
5
|
# @api private
|
7
6
|
class ItemData
|
8
7
|
def initialize(model_attributes, opts)
|
@@ -17,7 +16,6 @@ module Aws
|
|
17
16
|
|
18
17
|
populate_default_values
|
19
18
|
end
|
20
|
-
|
21
19
|
attr_accessor :new_record, :destroyed
|
22
20
|
|
23
21
|
def get_attribute(name)
|
@@ -75,7 +73,7 @@ module Aws
|
|
75
73
|
end
|
76
74
|
|
77
75
|
def dirty
|
78
|
-
@model_attributes.attributes.keys.
|
76
|
+
@model_attributes.attributes.keys.each_with_object([]) do |name, acc|
|
79
77
|
acc << name if attribute_dirty?(name)
|
80
78
|
acc
|
81
79
|
end
|
@@ -98,7 +96,7 @@ module Aws
|
|
98
96
|
end
|
99
97
|
|
100
98
|
def build_save_hash
|
101
|
-
@data.
|
99
|
+
@data.each_with_object({}) do |name_value_pair, acc|
|
102
100
|
attr_name, raw_value = name_value_pair
|
103
101
|
attribute = @model_attributes.attribute_for(attr_name)
|
104
102
|
if !raw_value.nil? || attribute.persist_nil?
|
@@ -120,11 +118,10 @@ module Aws
|
|
120
118
|
end
|
121
119
|
|
122
120
|
private
|
121
|
+
|
123
122
|
def _deep_copy(obj)
|
124
123
|
Marshal.load(Marshal.dump(obj))
|
125
124
|
end
|
126
|
-
|
127
125
|
end
|
128
|
-
|
129
126
|
end
|
130
127
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module ItemOperations
|
6
|
-
|
7
6
|
# @api private
|
8
7
|
def self.included(sub_class)
|
9
8
|
sub_class.extend(ItemOperationsClassMethods)
|
@@ -12,12 +11,12 @@ module Aws
|
|
12
11
|
# Saves this instance of an item to Amazon DynamoDB. If this item is "new"
|
13
12
|
# as defined by having new or altered key attributes, will attempt a
|
14
13
|
# conditional
|
15
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method
|
16
|
-
# call, which will not overwrite an existing
|
17
|
-
# altered non-key attributes, will perform an
|
18
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
19
|
-
# call. Uses this item instance's attributes
|
20
|
-
# request on your behalf.
|
14
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method
|
15
|
+
# Aws::DynamoDB::Client#put_item} call, which will not overwrite an existing
|
16
|
+
# item. If the item only has altered non-key attributes, will perform an
|
17
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
18
|
+
# Aws::DynamoDB::Client#update_item} call. Uses this item instance's attributes
|
19
|
+
# in order to build the request on your behalf.
|
21
20
|
#
|
22
21
|
# You can use the +:force+ option to perform a simple put/overwrite
|
23
22
|
# without conditional validation or update logic.
|
@@ -38,19 +37,19 @@ module Aws
|
|
38
37
|
if ret
|
39
38
|
ret
|
40
39
|
else
|
41
|
-
raise Errors::ValidationError
|
40
|
+
raise Errors::ValidationError, 'Validation hook returned false!'
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
44
|
# Saves this instance of an item to Amazon DynamoDB. If this item is "new"
|
46
45
|
# as defined by having new or altered key attributes, will attempt a
|
47
46
|
# conditional
|
48
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method
|
49
|
-
# call, which will not overwrite an
|
50
|
-
# altered non-key attributes, will perform an
|
51
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
52
|
-
# call. Uses this item instance's attributes
|
53
|
-
# request on your behalf.
|
47
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method
|
48
|
+
# Aws::DynamoDB::Client#put_item} call, which will not overwrite an
|
49
|
+
# existing item. If the item only has altered non-key attributes, will perform an
|
50
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
51
|
+
# Aws::DynamoDB::Client#update_item} call. Uses this item instance's attributes
|
52
|
+
# in order to build the request on your behalf.
|
54
53
|
#
|
55
54
|
# You can use the +:force+ option to perform a simple put/overwrite
|
56
55
|
# without conditional validation or update logic.
|
@@ -70,7 +69,6 @@ module Aws
|
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
73
|
-
|
74
72
|
# Assigns the attributes provided onto the model.
|
75
73
|
#
|
76
74
|
# @example Usage Example
|
@@ -99,7 +97,7 @@ module Aws
|
|
99
97
|
opts.each do |field, new_value|
|
100
98
|
field = field.to_sym
|
101
99
|
setter = "#{field}="
|
102
|
-
raise ArgumentError
|
100
|
+
raise ArgumentError, "Invalid field: #{field} for model" unless respond_to?(setter)
|
103
101
|
public_send(setter, new_value)
|
104
102
|
end
|
105
103
|
end
|
@@ -174,42 +172,42 @@ module Aws
|
|
174
172
|
|
175
173
|
# Deletes the item instance that matches the key values of this item
|
176
174
|
# instance in Amazon DynamoDB. Uses the
|
177
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method
|
178
|
-
# API.
|
175
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method
|
176
|
+
# Aws::DynamoDB::Client#delete_item} API.
|
179
177
|
def delete!
|
180
178
|
dynamodb_client.delete_item(
|
181
179
|
table_name: self.class.table_name,
|
182
180
|
key: key_values
|
183
181
|
)
|
184
|
-
|
182
|
+
instance_variable_get('@data').destroyed = true
|
185
183
|
end
|
186
184
|
|
187
185
|
# Validates and generates the key values necessary for API operations such as the
|
188
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method
|
189
|
-
# operation.
|
186
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method
|
187
|
+
# Aws::DynamoDB::Client#delete_item} operation.
|
190
188
|
def key_values
|
191
189
|
validate_key_values
|
192
190
|
attributes = self.class.attributes
|
193
191
|
self.class.keys.values.each_with_object({}) do |attr_name, hash|
|
194
192
|
db_name = attributes.storage_name_for(attr_name)
|
195
|
-
hash[db_name] = attributes
|
196
|
-
|
197
|
-
.serialize(@data.raw_value(attr_name))
|
193
|
+
hash[db_name] = attributes.attribute_for(attr_name)
|
194
|
+
.serialize(@data.raw_value(attr_name))
|
198
195
|
end
|
199
196
|
end
|
200
197
|
|
201
198
|
# Validates key values and returns a hash consisting of the parameters
|
202
199
|
# to save the record using the
|
203
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#batch_write_item-instance_method
|
204
|
-
# operation.
|
200
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#batch_write_item-instance_method
|
201
|
+
# Aws::DynamoDB::Client#batch_write_item} operation.
|
205
202
|
def save_values
|
206
203
|
_build_item_for_save
|
207
204
|
end
|
208
205
|
|
209
206
|
private
|
210
|
-
|
211
|
-
|
212
|
-
|
207
|
+
|
208
|
+
def _invalid_record?(_opts)
|
209
|
+
if respond_to?(:valid?)
|
210
|
+
if !valid?
|
213
211
|
true
|
214
212
|
else
|
215
213
|
false
|
@@ -234,12 +232,11 @@ module Aws
|
|
234
232
|
}.merge(prevent_overwrite_expression)
|
235
233
|
begin
|
236
234
|
dynamodb_client.put_item(put_opts)
|
237
|
-
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
|
238
|
-
raise Errors::ConditionalWriteFailed
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
)
|
235
|
+
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
|
236
|
+
raise Errors::ConditionalWriteFailed,
|
237
|
+
'Conditional #put_item call failed! Check that conditional write'\
|
238
|
+
' conditions are met, or include the :force option to clobber'\
|
239
|
+
' the remote item.'
|
243
240
|
end
|
244
241
|
else
|
245
242
|
update_pairs = _dirty_changes_for_update
|
@@ -253,7 +250,7 @@ module Aws
|
|
253
250
|
table_name: self.class.table_name,
|
254
251
|
key: key_values,
|
255
252
|
update_expression: uex,
|
256
|
-
expression_attribute_names: exp_attr_names
|
253
|
+
expression_attribute_names: exp_attr_names
|
257
254
|
}
|
258
255
|
request_opts[:expression_attribute_values] = exp_attr_values unless exp_attr_values.empty?
|
259
256
|
dynamodb_client.update_item(request_opts)
|
@@ -264,7 +261,7 @@ module Aws
|
|
264
261
|
)
|
265
262
|
end
|
266
263
|
end
|
267
|
-
data =
|
264
|
+
data = instance_variable_get('@data')
|
268
265
|
data.destroyed = false
|
269
266
|
data.new_record = false
|
270
267
|
true
|
@@ -278,15 +275,11 @@ module Aws
|
|
278
275
|
|
279
276
|
def validate_key_values
|
280
277
|
missing = missing_key_values
|
281
|
-
unless missing.empty?
|
282
|
-
raise Errors::KeyMissing.new(
|
283
|
-
"Missing required keys: #{missing.join(', ')}"
|
284
|
-
)
|
285
|
-
end
|
278
|
+
raise Errors::KeyMissing, "Missing required keys: #{missing.join(', ')}" unless missing.empty?
|
286
279
|
end
|
287
280
|
|
288
281
|
def missing_key_values
|
289
|
-
self.class.keys.
|
282
|
+
self.class.keys.each_with_object([]) do |key, acc|
|
290
283
|
acc << key.last if @data.raw_value(key.last).nil?
|
291
284
|
acc
|
292
285
|
end
|
@@ -302,24 +295,23 @@ module Aws
|
|
302
295
|
def prevent_overwrite_expression
|
303
296
|
conditions = []
|
304
297
|
expression_attribute_names = {}
|
305
|
-
keys = self.class.instance_variable_get(
|
298
|
+
keys = self.class.instance_variable_get('@keys')
|
306
299
|
# Hash Key
|
307
|
-
conditions <<
|
308
|
-
expression_attribute_names[
|
300
|
+
conditions << 'attribute_not_exists(#H)'
|
301
|
+
expression_attribute_names['#H'] = keys.hash_key_attribute.database_name
|
309
302
|
# Range Key
|
310
303
|
if self.class.range_key
|
311
|
-
conditions <<
|
312
|
-
expression_attribute_names[
|
304
|
+
conditions << 'attribute_not_exists(#R)'
|
305
|
+
expression_attribute_names['#R'] = keys.range_key_attribute.database_name
|
313
306
|
end
|
314
307
|
{
|
315
|
-
condition_expression: conditions.join(
|
308
|
+
condition_expression: conditions.join(' and '),
|
316
309
|
expression_attribute_names: expression_attribute_names
|
317
310
|
}
|
318
311
|
end
|
319
312
|
|
320
313
|
def _dirty_changes_for_update
|
321
|
-
|
322
|
-
ret = dirty.inject({}) do |acc, attr_name|
|
314
|
+
ret = dirty.each_with_object({}) do |attr_name, acc|
|
323
315
|
acc[attr_name] = @data.raw_value(attr_name)
|
324
316
|
acc
|
325
317
|
end
|
@@ -327,7 +319,6 @@ module Aws
|
|
327
319
|
end
|
328
320
|
|
329
321
|
module ItemOperationsClassMethods
|
330
|
-
|
331
322
|
# @example Usage Example
|
332
323
|
# check_exp = Model.transact_check_expression(
|
333
324
|
# key: { uuid: "foo" },
|
@@ -347,9 +338,10 @@ module Aws
|
|
347
338
|
#
|
348
339
|
# @param [Hash] opts Options matching the :condition_check contents in
|
349
340
|
# the
|
350
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_write_items-instance_method
|
351
|
-
# API, with the exception that
|
352
|
-
#
|
341
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_write_items-instance_method
|
342
|
+
# Aws::DynamoDB::Client#transact_write_items} API, with the exception that
|
343
|
+
# keys will be marshalled for you, and the table name will be provided
|
344
|
+
# for you by the operation.
|
353
345
|
# @return [Hash] Options suitable to be used as a check expression when
|
354
346
|
# calling the +#transact_write+ operation.
|
355
347
|
def transact_check_expression(opts)
|
@@ -359,13 +351,11 @@ module Aws
|
|
359
351
|
check_key = {}
|
360
352
|
@keys.keys.each_value do |attr_sym|
|
361
353
|
unless key[attr_sym]
|
362
|
-
raise Errors::KeyMissing
|
363
|
-
"Missing required key #{attr_sym} in #{key}"
|
364
|
-
)
|
354
|
+
raise Errors::KeyMissing, "Missing required key #{attr_sym} in #{key}"
|
365
355
|
end
|
366
356
|
attr_name = attributes.storage_name_for(attr_sym)
|
367
|
-
check_key[attr_name] = attributes.attribute_for(attr_sym)
|
368
|
-
|
357
|
+
check_key[attr_name] = attributes.attribute_for(attr_sym)
|
358
|
+
.serialize(key[attr_sym])
|
369
359
|
end
|
370
360
|
opts[:key] = check_key
|
371
361
|
opts[:table_name] = table_name
|
@@ -385,13 +375,11 @@ module Aws
|
|
385
375
|
request_key = {}
|
386
376
|
@keys.keys.each_value do |attr_sym|
|
387
377
|
unless key[attr_sym]
|
388
|
-
raise Errors::KeyMissing
|
389
|
-
"Missing required key #{attr_sym} in #{key}"
|
390
|
-
)
|
378
|
+
raise Errors::KeyMissing, "Missing required key #{attr_sym} in #{key}"
|
391
379
|
end
|
392
380
|
attr_name = attributes.storage_name_for(attr_sym)
|
393
|
-
request_key[attr_name] = attributes.attribute_for(attr_sym)
|
394
|
-
|
381
|
+
request_key[attr_name] = attributes.attribute_for(attr_sym)
|
382
|
+
.serialize(key[attr_sym])
|
395
383
|
end
|
396
384
|
# this is a :get item used by #transact_get_items, with the exception
|
397
385
|
# of :model_class which needs to be removed before passing along
|
@@ -422,10 +410,11 @@ module Aws
|
|
422
410
|
# or virtual tables.
|
423
411
|
#
|
424
412
|
# @param [Hash] opts Options to pass through to
|
425
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_get_items-instance_method
|
426
|
-
# with the exception of the
|
427
|
-
# +#tfind_opts+ operation on
|
428
|
-
# metadata used to marshal your
|
413
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_get_items-instance_method
|
414
|
+
# Aws::DynamoDB::Client#transact_get_items}, with the exception of the
|
415
|
+
# :transact_items array, which uses the +#tfind_opts+ operation on
|
416
|
+
# your model class to provide extra metadata used to marshal your
|
417
|
+
# items after retrieval.
|
429
418
|
# @option opts [Array] :transact_items A set of options describing
|
430
419
|
# instances of the model class to return.
|
431
420
|
# @return [OpenStruct] Structured like the client API response from
|
@@ -492,13 +481,11 @@ module Aws
|
|
492
481
|
request_key = {}
|
493
482
|
@keys.keys.each_value do |attr_sym|
|
494
483
|
unless key[attr_sym]
|
495
|
-
raise Errors::KeyMissing
|
496
|
-
"Missing required key #{attr_sym} in #{key}"
|
497
|
-
)
|
484
|
+
raise Errors::KeyMissing, "Missing required key #{attr_sym} in #{key}"
|
498
485
|
end
|
499
486
|
attr_name = attributes.storage_name_for(attr_sym)
|
500
|
-
request_key[attr_name] = attributes.attribute_for(attr_sym)
|
501
|
-
|
487
|
+
request_key[attr_name] = attributes.attribute_for(attr_sym)
|
488
|
+
.serialize(key[attr_sym])
|
502
489
|
end
|
503
490
|
request_opts = {
|
504
491
|
table_name: table_name,
|
@@ -512,7 +499,6 @@ module Aws
|
|
512
499
|
end
|
513
500
|
end
|
514
501
|
|
515
|
-
|
516
502
|
# @example Usage Example
|
517
503
|
# class MyModel
|
518
504
|
# include Aws::Record
|
@@ -561,9 +547,9 @@ module Aws
|
|
561
547
|
# MyModel.update(id: 1, name: "First", body: "Hello!")
|
562
548
|
#
|
563
549
|
# Performs an
|
564
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
565
|
-
# call immediately on the table,
|
566
|
-
# provided.
|
550
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method
|
551
|
+
# Aws::DynamoDB::Client#update_item} call immediately on the table,
|
552
|
+
# using the attribute key/value pairs provided.
|
567
553
|
#
|
568
554
|
# @param [Hash] opts attribute-value pairs for the update operation you
|
569
555
|
# wish to perform. You must include all key attributes for a valid
|
@@ -573,12 +559,10 @@ module Aws
|
|
573
559
|
# not include all table keys.
|
574
560
|
def update(opts)
|
575
561
|
key = {}
|
576
|
-
updates = {}
|
577
562
|
@keys.keys.each_value do |attr_sym|
|
578
|
-
unless value = opts.delete(attr_sym)
|
579
|
-
raise Errors::KeyMissing
|
580
|
-
|
581
|
-
)
|
563
|
+
unless (value = opts.delete(attr_sym))
|
564
|
+
raise Errors::KeyMissing, "Missing required key #{attr_sym} in #{opts}"
|
565
|
+
|
582
566
|
end
|
583
567
|
attr_name = attributes.storage_name_for(attr_sym)
|
584
568
|
key[attr_name] = attributes.attribute_for(attr_sym).serialize(value)
|
@@ -598,16 +582,17 @@ module Aws
|
|
598
582
|
end
|
599
583
|
|
600
584
|
private
|
585
|
+
|
601
586
|
def _build_update_expression(attr_value_pairs)
|
602
587
|
set_expressions = []
|
603
588
|
remove_expressions = []
|
604
589
|
exp_attr_names = {}
|
605
590
|
exp_attr_values = {}
|
606
|
-
name_sub_token =
|
607
|
-
value_sub_token =
|
591
|
+
name_sub_token = 'UE_A'
|
592
|
+
value_sub_token = 'ue_a'
|
608
593
|
attr_value_pairs.each do |attr_sym, value|
|
609
|
-
name_sub =
|
610
|
-
value_sub =
|
594
|
+
name_sub = '#' + name_sub_token
|
595
|
+
value_sub = ':' + value_sub_token
|
611
596
|
name_sub_token = name_sub_token.succ
|
612
597
|
value_sub_token = value_sub_token.succ
|
613
598
|
|
@@ -615,7 +600,7 @@ module Aws
|
|
615
600
|
attr_name = attributes.storage_name_for(attr_sym)
|
616
601
|
exp_attr_names[name_sub] = attr_name
|
617
602
|
if _update_type_remove?(attribute, value)
|
618
|
-
remove_expressions <<
|
603
|
+
remove_expressions << name_sub.to_s
|
619
604
|
else
|
620
605
|
set_expressions << "#{name_sub} = #{value_sub}"
|
621
606
|
exp_attr_values[value_sub] = attribute.serialize(value)
|
@@ -623,21 +608,21 @@ module Aws
|
|
623
608
|
end
|
624
609
|
update_expressions = []
|
625
610
|
unless set_expressions.empty?
|
626
|
-
update_expressions <<
|
611
|
+
update_expressions << 'SET ' + set_expressions.join(', ')
|
627
612
|
end
|
628
613
|
unless remove_expressions.empty?
|
629
|
-
update_expressions <<
|
614
|
+
update_expressions << 'REMOVE ' + remove_expressions.join(', ')
|
630
615
|
end
|
631
616
|
if update_expressions.empty?
|
632
617
|
nil
|
633
618
|
else
|
634
|
-
[update_expressions.join(
|
619
|
+
[update_expressions.join(' '), exp_attr_names, exp_attr_values]
|
635
620
|
end
|
636
621
|
end
|
637
622
|
|
638
623
|
def build_item_from_resp(resp)
|
639
624
|
record = new
|
640
|
-
data = record.instance_variable_get(
|
625
|
+
data = record.instance_variable_get('@data')
|
641
626
|
attributes.attributes.each do |name, attr|
|
642
627
|
data.set_attribute(name, attr.extract(resp.item))
|
643
628
|
data.new_record = false
|
@@ -649,7 +634,6 @@ module Aws
|
|
649
634
|
value.nil? && !attribute.persist_nil?
|
650
635
|
end
|
651
636
|
end
|
652
|
-
|
653
637
|
end
|
654
638
|
end
|
655
639
|
end
|