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