aws-record 2.4.1 → 2.7.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/lib/aws-record/record/attribute.rb +1 -3
- data/lib/aws-record/record/batch.rb +82 -0
- data/lib/aws-record/record/batch_write.rb +81 -0
- data/lib/aws-record/record/buildable_search.rb +60 -15
- data/lib/aws-record/record/client_configuration.rb +63 -0
- data/lib/aws-record/record/item_collection.rb +5 -2
- data/lib/aws-record/record/item_operations.rb +32 -22
- data/lib/aws-record/record/table_migration.rb +50 -9
- data/lib/aws-record/record/transactions.rb +7 -52
- data/lib/aws-record/record/version.rb +1 -1
- data/lib/aws-record/record.rb +10 -51
- data/lib/aws-record.rb +3 -0
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67f48531ca8b917f680a1d9a5d21afd1611aba0eb96916a5783addaf7939cda8
|
4
|
+
data.tar.gz: 7f6cbb16271455ada17a61f32106800b65d3b4103a5254e7686e06d5cf715cca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bb474f4d13e469b9af991e061b10a54279f37d7390b9cb1bffafd40d039c649c12ca5423140d4a232a08536ec715df89db2e07f6670ef0242732cbe78d1d890
|
7
|
+
data.tar.gz: 9b61d0d93ce9b657989fefde1201aab35253e656035ffb87ccbebfbafe4ea423883146dd4dec510dfdf5deec74b274784f6490d86804cf76b09aeee58f41cdfb
|
@@ -53,9 +53,7 @@ module Aws
|
|
53
53
|
@marshaler = options[:marshaler] || DefaultMarshaler
|
54
54
|
@persist_nil = options[:persist_nil]
|
55
55
|
dv = options[:default_value]
|
56
|
-
|
57
|
-
@default_value_or_lambda = _is_lambda?(dv) ? dv : type_cast(dv)
|
58
|
-
end
|
56
|
+
@default_value_or_lambda = _is_lambda?(dv) ? dv : type_cast(dv)
|
59
57
|
end
|
60
58
|
|
61
59
|
# Attempts to type cast a raw value into the attribute's type. This call
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright 2015-2021 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
|
+
class Batch
|
17
|
+
extend ClientConfiguration
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# @example Usage Example
|
21
|
+
# class Breakfast
|
22
|
+
# include Aws::Record
|
23
|
+
# integer_attr :id, hash_key: true
|
24
|
+
# string_attr :name, range_key: true
|
25
|
+
# string_attr :body
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # setup
|
29
|
+
# eggs = Breakfast.new(id: 1, name: "eggs").save!
|
30
|
+
# waffles = Breakfast.new(id: 2, name: "waffles")
|
31
|
+
# pancakes = Breakfast.new(id: 3, name: "pancakes")
|
32
|
+
#
|
33
|
+
# # batch operations
|
34
|
+
# operation = Aws::Record::Batch.write(client: Breakfast.dynamodb_client) do |db|
|
35
|
+
# db.put(waffles)
|
36
|
+
# db.delete(eggs)
|
37
|
+
# db.put(pancakes)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # unprocessed items can be retried by calling Aws::Record::BatchWrite#execute!
|
41
|
+
# operation.execute! unless operation.complete?
|
42
|
+
#
|
43
|
+
# Provides a thin wrapper to the
|
44
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#batch_write_item-instance_method Aws::DynamoDB::Client#batch_write_item}
|
45
|
+
# method. Up to 25 +PutItem+ or +DeleteItem+ operations are supported.
|
46
|
+
# A single rquest may write up to 16 MB of data, with each item having a
|
47
|
+
# write limit of 400 KB.
|
48
|
+
#
|
49
|
+
# *Note*: this operation does not support dirty attribute handling,
|
50
|
+
# nor does it enforce safe write operations (i.e. update vs new record
|
51
|
+
# checks).
|
52
|
+
#
|
53
|
+
# This call may partially execute write operations. Failed operations
|
54
|
+
# are returned as +Aws::Record::BatchWrite#unprocessed_items+ (i.e. the
|
55
|
+
# table fails to meet requested write capacity). Any unprocessed
|
56
|
+
# items may be retried by calling +Aws::Record::BatchWrite#execute!+
|
57
|
+
# again. You can determine if the request needs to be retried by calling
|
58
|
+
# the +Aws::Record::BatchWrite#complete?+ method - which returns +true+
|
59
|
+
# when all operations have been completed.
|
60
|
+
#
|
61
|
+
# Please see
|
62
|
+
# {https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.Errors.html#Programming.Errors.BatchOperations Batch Operations and Error Handling}
|
63
|
+
# in the DynamoDB Developer Guide for more details.
|
64
|
+
#
|
65
|
+
# @param [Hash] opts the options you wish to use to create the client.
|
66
|
+
# Note that if you include the option +:client+, all other options
|
67
|
+
# will be ignored. See the documentation for other options in the
|
68
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#initialize-instance_method AWS SDK for Ruby}.
|
69
|
+
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in your
|
70
|
+
# own pre-configured client.
|
71
|
+
#
|
72
|
+
# @return [Aws::Record::BatchWrite] An instance that contains any
|
73
|
+
# unprocessed items and allows for a retry strategy.
|
74
|
+
def write(opts = {}, &block)
|
75
|
+
batch = BatchWrite.new(client: _build_client(opts))
|
76
|
+
block.call(batch)
|
77
|
+
batch.execute!
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# Copyright 2015-2021 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
|
+
class BatchWrite
|
17
|
+
# @param [Aws::DynamoDB::Client] client the DynamoDB SDK client.
|
18
|
+
def initialize(client:)
|
19
|
+
@client = client
|
20
|
+
end
|
21
|
+
|
22
|
+
# Append a +PutItem+ operation to a batch write request.
|
23
|
+
#
|
24
|
+
# @param [Aws::Record] record a model class that includes {Aws::Record}.
|
25
|
+
def put(record)
|
26
|
+
table_name, params = record_put_params(record)
|
27
|
+
operations[table_name] ||= []
|
28
|
+
operations[table_name] << { put_request: params }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Append a +DeleteItem+ operation to a batch write request.
|
32
|
+
#
|
33
|
+
# @param [Aws::Record] record a model class that includes {Aws::Record}.
|
34
|
+
def delete(record)
|
35
|
+
table_name, params = record_delete_params(record)
|
36
|
+
operations[table_name] ||= []
|
37
|
+
operations[table_name] << { delete_request: params }
|
38
|
+
end
|
39
|
+
|
40
|
+
# Perform a +batch_write_item+ request.
|
41
|
+
#
|
42
|
+
# @return [Aws::Record::BatchWrite] an instance that provides access to
|
43
|
+
# unprocessed items and allows for retries.
|
44
|
+
def execute!
|
45
|
+
result = @client.batch_write_item(request_items: operations)
|
46
|
+
@operations = result.unprocessed_items
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Indicates if all items have been processed.
|
51
|
+
#
|
52
|
+
# @return [Boolean] +true+ if +unprocessed_items+ is empty, +false+
|
53
|
+
# otherwise
|
54
|
+
def complete?
|
55
|
+
unprocessed_items.values.none?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns all +DeleteItem+ and +PutItem+ operations that have not yet been
|
59
|
+
# processed successfully.
|
60
|
+
#
|
61
|
+
# @return [Hash] All operations that have not yet successfully completed.
|
62
|
+
def unprocessed_items
|
63
|
+
operations
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def operations
|
69
|
+
@operations ||= {}
|
70
|
+
end
|
71
|
+
|
72
|
+
def record_delete_params(record)
|
73
|
+
[record.class.table_name, { key: record.key_values }]
|
74
|
+
end
|
75
|
+
|
76
|
+
def record_put_params(record)
|
77
|
+
[record.class.table_name, { item: record.save_values }]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -101,9 +101,9 @@ module Aws
|
|
101
101
|
@params[:expression_attribute_values] = {}
|
102
102
|
values = @params[:expression_attribute_values]
|
103
103
|
end
|
104
|
-
_key_pass(statement_str, names)
|
105
|
-
_apply_values(
|
106
|
-
@params[:key_condition_expression] =
|
104
|
+
prepared = _key_pass(statement_str, names)
|
105
|
+
statement = _apply_values(prepared, subs, values)
|
106
|
+
@params[:key_condition_expression] = statement
|
107
107
|
self
|
108
108
|
end
|
109
109
|
|
@@ -123,7 +123,7 @@ module Aws
|
|
123
123
|
# "contains(:body, ?)",
|
124
124
|
# "bacon"
|
125
125
|
# ).complete!
|
126
|
-
#
|
126
|
+
#
|
127
127
|
def filter_expr(statement_str, *subs)
|
128
128
|
names = @params[:expression_attribute_names]
|
129
129
|
if names.nil?
|
@@ -135,9 +135,9 @@ module Aws
|
|
135
135
|
@params[:expression_attribute_values] = {}
|
136
136
|
values = @params[:expression_attribute_values]
|
137
137
|
end
|
138
|
-
_key_pass(statement_str, names)
|
139
|
-
_apply_values(
|
140
|
-
@params[:filter_expression] =
|
138
|
+
prepared = _key_pass(statement_str, names)
|
139
|
+
statement = _apply_values(prepared, subs, values)
|
140
|
+
@params[:filter_expression] = statement
|
141
141
|
self
|
142
142
|
end
|
143
143
|
|
@@ -167,8 +167,8 @@ module Aws
|
|
167
167
|
@params[:expression_attribute_names] = {}
|
168
168
|
names = @params[:expression_attribute_names]
|
169
169
|
end
|
170
|
-
_key_pass(statement_str, names)
|
171
|
-
@params[:projection_expression] =
|
170
|
+
prepared = _key_pass(statement_str, names)
|
171
|
+
@params[:projection_expression] = prepared
|
172
172
|
self
|
173
173
|
end
|
174
174
|
|
@@ -178,6 +178,50 @@ module Aws
|
|
178
178
|
self
|
179
179
|
end
|
180
180
|
|
181
|
+
# Allows you to define a callback that will determine the model class
|
182
|
+
# to be used for each item, allowing queries to return an ItemCollection
|
183
|
+
# with mixed models. The provided block must return the model class based on
|
184
|
+
# any logic on the raw item attributes or `nil` if no model applies and
|
185
|
+
# the item should be skipped. Note: The block only has access to raw item
|
186
|
+
# data so attributes must be accessed using their names as defined in the
|
187
|
+
# table, not as the symbols defined in the model class(s).
|
188
|
+
#
|
189
|
+
# @example Scan with heterogeneous results:
|
190
|
+
# # Example model classes
|
191
|
+
# class Model_A
|
192
|
+
# include Aws::Record
|
193
|
+
# set_table_name(TABLE_NAME)
|
194
|
+
#
|
195
|
+
# string_attr :uuid, hash_key: true
|
196
|
+
# string_attr :class_name, range_key: true
|
197
|
+
#
|
198
|
+
# string_attr :attr_a
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# class Model_B
|
202
|
+
# include Aws::Record
|
203
|
+
# set_table_name(TABLE_NAME)
|
204
|
+
#
|
205
|
+
# string_attr :uuid, hash_key: true
|
206
|
+
# string_attr :class_name, range_key: true
|
207
|
+
#
|
208
|
+
# string_attr :attr_b
|
209
|
+
# end
|
210
|
+
#
|
211
|
+
# # use multi_model_filter to create a query on TABLE_NAME
|
212
|
+
# items = Model_A.build_scan.multi_model_filter do |raw_item_attributes|
|
213
|
+
# case raw_item_attributes['class_name']
|
214
|
+
# when "A" then Model_A
|
215
|
+
# when "B" then Model_B
|
216
|
+
# else
|
217
|
+
# nil
|
218
|
+
# end
|
219
|
+
# end.complete!
|
220
|
+
def multi_model_filter(proc = nil, &block)
|
221
|
+
@params[:model_filter] = proc || block
|
222
|
+
self
|
223
|
+
end
|
224
|
+
|
181
225
|
# You must call this method at the end of any query or scan you build.
|
182
226
|
#
|
183
227
|
# @return [Aws::Record::ItemCollection] The item collection lazy
|
@@ -188,8 +232,8 @@ module Aws
|
|
188
232
|
|
189
233
|
private
|
190
234
|
def _key_pass(statement, names)
|
191
|
-
statement.gsub
|
192
|
-
key = match.gsub
|
235
|
+
statement.gsub(/:(\w+)/) do |match|
|
236
|
+
key = match.gsub(':','').to_sym
|
193
237
|
key_name = @model.attributes.storage_name_for(key)
|
194
238
|
if key_name
|
195
239
|
sub_name = _next_name
|
@@ -204,15 +248,16 @@ module Aws
|
|
204
248
|
|
205
249
|
def _apply_values(statement, subs, values)
|
206
250
|
count = 0
|
207
|
-
statement.gsub
|
251
|
+
statement.gsub(/[?]/) do |match|
|
208
252
|
sub_value = _next_value
|
209
253
|
raise "Substitution collision!" if values[sub_value]
|
210
254
|
values[sub_value] = subs[count]
|
211
255
|
count += 1
|
212
256
|
sub_value
|
213
|
-
end
|
214
|
-
|
215
|
-
|
257
|
+
end.tap do
|
258
|
+
unless count == subs.size
|
259
|
+
raise "Expected #{count} values in the substitution set, but found #{subs.size}"
|
260
|
+
end
|
216
261
|
end
|
217
262
|
end
|
218
263
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright 2015-2021 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
|
+
module ClientConfiguration
|
17
|
+
# Configures the Amazon DynamoDB client used by this class and all
|
18
|
+
# instances of this class.
|
19
|
+
#
|
20
|
+
# Please note that this method is also called internally when you first
|
21
|
+
# attempt to perform an operation against the remote end, if you have not
|
22
|
+
# already configured a client. As such, please read and understand the
|
23
|
+
# documentation in the AWS SDK for Ruby around
|
24
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/index.html#Configuration configuration}
|
25
|
+
# to ensure you understand how default configuration behavior works. When
|
26
|
+
# in doubt, call this method to ensure your client is configured the way
|
27
|
+
# you want it to be configured.
|
28
|
+
#
|
29
|
+
# @param [Hash] opts the options you wish to use to create the client.
|
30
|
+
# Note that if you include the option +:client+, all other options
|
31
|
+
# will be ignored. See the documentation for other options in the
|
32
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#initialize-instance_method AWS SDK for Ruby}.
|
33
|
+
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in your
|
34
|
+
# own pre-configured client.
|
35
|
+
def configure_client(opts = {})
|
36
|
+
@dynamodb_client = _build_client(opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Gets the
|
40
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html}
|
41
|
+
# instance that Transactions use. When called for the first time, if
|
42
|
+
# {#configure_client} has not yet been called, will configure a new
|
43
|
+
# client for you with default parameters.
|
44
|
+
#
|
45
|
+
# @return [Aws::DynamoDB::Client] the Amazon DynamoDB client instance.
|
46
|
+
def dynamodb_client
|
47
|
+
@dynamodb_client ||= configure_client
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def _build_client(opts = {})
|
53
|
+
provided_client = opts.delete(:client)
|
54
|
+
opts[:user_agent_suffix] = _user_agent(opts.delete(:user_agent_suffix))
|
55
|
+
provided_client || Aws::DynamoDB::Client.new(opts)
|
56
|
+
end
|
57
|
+
|
58
|
+
def _user_agent(custom)
|
59
|
+
custom || " aws-record/#{VERSION}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -19,6 +19,7 @@ module Aws
|
|
19
19
|
def initialize(search_method, search_params, model, client)
|
20
20
|
@search_method = search_method
|
21
21
|
@search_params = search_params
|
22
|
+
@model_filter = @search_params.delete(:model_filter)
|
22
23
|
@model = model
|
23
24
|
@client = client
|
24
25
|
end
|
@@ -91,9 +92,11 @@ module Aws
|
|
91
92
|
def _build_items_from_response(items, model)
|
92
93
|
ret = []
|
93
94
|
items.each do |item|
|
94
|
-
|
95
|
+
model_class = @model_filter ? @model_filter.call(item) : model
|
96
|
+
next unless model_class
|
97
|
+
record = model_class.new
|
95
98
|
data = record.instance_variable_get("@data")
|
96
|
-
|
99
|
+
model_class.attributes.attributes.each do |name, attr|
|
97
100
|
data.set_attribute(name, attr.extract(item))
|
98
101
|
end
|
99
102
|
data.clean!
|
@@ -82,8 +82,7 @@ module Aws
|
|
82
82
|
end
|
83
83
|
|
84
84
|
|
85
|
-
#
|
86
|
-
# instance in Amazon DynamoDB.
|
85
|
+
# Assigns the attributes provided onto the model.
|
87
86
|
#
|
88
87
|
# @example Usage Example
|
89
88
|
# class MyModel
|
@@ -98,13 +97,13 @@ module Aws
|
|
98
97
|
# model.age # => 4
|
99
98
|
# model.height # => 70.5
|
100
99
|
# model.save
|
101
|
-
# model.dirty? # => false
|
102
|
-
#
|
100
|
+
# model.dirty? # => false
|
101
|
+
#
|
103
102
|
# model.assign_attributes(age: 5, height: 150.75)
|
104
103
|
# model.age # => 5
|
105
104
|
# model.height # => 150.75
|
106
105
|
# model.dirty? # => true
|
107
|
-
#
|
106
|
+
#
|
108
107
|
#
|
109
108
|
# @param [Hash] opts
|
110
109
|
def assign_attributes(opts)
|
@@ -138,14 +137,14 @@ module Aws
|
|
138
137
|
# model.age # => 4
|
139
138
|
# model.height # => 70.5
|
140
139
|
# model.save
|
141
|
-
# model.dirty? # => false
|
142
|
-
#
|
140
|
+
# model.dirty? # => false
|
141
|
+
#
|
143
142
|
# model.update(age: 5, height: 150.75)
|
144
143
|
# model.age # => 5
|
145
144
|
# model.height # => 150.75
|
146
145
|
# model.dirty? # => false
|
147
146
|
#
|
148
|
-
#
|
147
|
+
#
|
149
148
|
# @param [Hash] new_param, contains the new parameters for the model
|
150
149
|
#
|
151
150
|
# @param [Hash] opts
|
@@ -168,7 +167,7 @@ module Aws
|
|
168
167
|
# Note that aws-record allows you to change your model's key values,
|
169
168
|
# but this will be interpreted as persisting a new item to your DynamoDB
|
170
169
|
# table
|
171
|
-
#
|
170
|
+
#
|
172
171
|
# @param [Hash] new_param, contains the new parameters for the model
|
173
172
|
#
|
174
173
|
# @param [Hash] opts
|
@@ -196,6 +195,28 @@ module Aws
|
|
196
195
|
self.instance_variable_get("@data").destroyed = true
|
197
196
|
end
|
198
197
|
|
198
|
+
# Validates and generates the key values necessary for API operations such as the
|
199
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method Aws::DynamoDB::Client#delete_item}
|
200
|
+
# operation.
|
201
|
+
def key_values
|
202
|
+
validate_key_values
|
203
|
+
attributes = self.class.attributes
|
204
|
+
self.class.keys.values.each_with_object({}) do |attr_name, hash|
|
205
|
+
db_name = attributes.storage_name_for(attr_name)
|
206
|
+
hash[db_name] = attributes
|
207
|
+
.attribute_for(attr_name)
|
208
|
+
.serialize(@data.raw_value(attr_name))
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Validates key values and returns a hash consisting of the parameters
|
213
|
+
# to save the record using the
|
214
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#batch_write_item-instance_method Aws::DynamoDB::Client#batch_write_item}
|
215
|
+
# operation.
|
216
|
+
def save_values
|
217
|
+
_build_item_for_save
|
218
|
+
end
|
219
|
+
|
199
220
|
private
|
200
221
|
def _invalid_record?(opts)
|
201
222
|
if self.respond_to?(:valid?)
|
@@ -266,17 +287,6 @@ module Aws
|
|
266
287
|
@data.build_save_hash
|
267
288
|
end
|
268
289
|
|
269
|
-
def key_values
|
270
|
-
validate_key_values
|
271
|
-
attributes = self.class.attributes
|
272
|
-
self.class.keys.inject({}) do |acc, (_, attr_name)|
|
273
|
-
db_name = attributes.storage_name_for(attr_name)
|
274
|
-
acc[db_name] = attributes.attribute_for(attr_name).
|
275
|
-
serialize(@data.raw_value(attr_name))
|
276
|
-
acc
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
290
|
def validate_key_values
|
281
291
|
missing = missing_key_values
|
282
292
|
unless missing.empty?
|
@@ -340,7 +350,7 @@ module Aws
|
|
340
350
|
# ":v" => 1024
|
341
351
|
# }
|
342
352
|
# )
|
343
|
-
#
|
353
|
+
#
|
344
354
|
# Allows you to build a "check" expression for use in transactional
|
345
355
|
# write operations.
|
346
356
|
#
|
@@ -401,7 +411,7 @@ module Aws
|
|
401
411
|
# string_attr :hk, hash_key: true
|
402
412
|
# string_attr :rk, range_key: true
|
403
413
|
# end
|
404
|
-
#
|
414
|
+
#
|
405
415
|
# results = Table.transact_find(
|
406
416
|
# transact_items: [
|
407
417
|
# {key: { hk: "hk1", rk: "rk1"}},
|
@@ -56,15 +56,24 @@ module Aws
|
|
56
56
|
# @param [Hash] opts options to pass on to the client call to
|
57
57
|
# +#create_table+. See the documentation above in the AWS SDK for Ruby
|
58
58
|
# V2.
|
59
|
-
# @option opts [Hash] :
|
60
|
-
#
|
59
|
+
# @option opts [Hash] :billing_mode Accepts values 'PAY_PER_REQUEST' or
|
60
|
+
# 'PROVISIONED'. If :provisioned_throughput option is specified, this
|
61
|
+
# option is not required, as 'PROVISIONED' is assumed. If
|
62
|
+
# :provisioned_throughput is not specified, this option is required
|
63
|
+
# and must be set to 'PAY_PER_REQUEST'.
|
64
|
+
# @option opts [Hash] :provisioned_throughput Unless :billing_mode is
|
65
|
+
# set to 'PAY_PER_REQUEST', this is a required argument, in which
|
66
|
+
# you must specify the +:read_capacity_units+ and
|
61
67
|
# +:write_capacity_units+ of your new table.
|
62
68
|
# @option opts [Hash] :global_secondary_index_throughput This argument is
|
63
|
-
# required if you define any global secondary indexes
|
69
|
+
# required if you define any global secondary indexes, unless
|
70
|
+
# :billing_mode is set to 'PAY_PER_REQUEST'. It should map your
|
64
71
|
# global secondary index names to their provisioned throughput, similar
|
65
72
|
# to how you define the provisioned throughput for the table in general.
|
66
73
|
def create!(opts)
|
67
74
|
gsit = opts.delete(:global_secondary_index_throughput)
|
75
|
+
_validate_billing(opts)
|
76
|
+
|
68
77
|
create_opts = opts.merge({
|
69
78
|
table_name: @model.table_name,
|
70
79
|
attribute_definitions: _attribute_definitions,
|
@@ -75,14 +84,19 @@ module Aws
|
|
75
84
|
_append_to_attribute_definitions(lsis, create_opts)
|
76
85
|
end
|
77
86
|
if gsis = @model.global_secondary_indexes_for_migration
|
78
|
-
unless gsit
|
87
|
+
unless gsit || opts[:billing_mode] == 'PAY_PER_REQUEST'
|
79
88
|
raise ArgumentError.new(
|
80
|
-
|
81
|
-
|
89
|
+
'If you define global secondary indexes, you must also define'\
|
90
|
+
' :global_secondary_index_throughput on table creation,'\
|
91
|
+
" unless :billing_mode is set to 'PAY_PER_REQUEST'."
|
82
92
|
)
|
83
93
|
end
|
84
|
-
|
85
|
-
|
94
|
+
gsis_opts = if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
95
|
+
gsis
|
96
|
+
else
|
97
|
+
_add_throughput_to_gsis(gsis, gsit)
|
98
|
+
end
|
99
|
+
create_opts[:global_secondary_indexes] = gsis_opts
|
86
100
|
_append_to_attribute_definitions(gsis, create_opts)
|
87
101
|
end
|
88
102
|
@client.create_table(create_opts)
|
@@ -142,6 +156,33 @@ module Aws
|
|
142
156
|
end
|
143
157
|
end
|
144
158
|
|
159
|
+
def _validate_billing(opts)
|
160
|
+
valid_modes = %w[PAY_PER_REQUEST PROVISIONED]
|
161
|
+
if opts.key?(:billing_mode)
|
162
|
+
unless valid_modes.include?(opts[:billing_mode])
|
163
|
+
raise ArgumentError.new(
|
164
|
+
":billing_mode option must be one of #{valid_modes.join(', ')}"\
|
165
|
+
" current value is: #{opts[:billing_mode]}"
|
166
|
+
)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
if opts.key?(:provisioned_throughput)
|
170
|
+
if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
171
|
+
raise ArgumentError.new(
|
172
|
+
'when :provisioned_throughput option is specified, :billing_mode'\
|
173
|
+
" must either be unspecified or have a value of 'PROVISIONED'"
|
174
|
+
)
|
175
|
+
end
|
176
|
+
else
|
177
|
+
if opts[:billing_mode] != 'PAY_PER_REQUEST'
|
178
|
+
raise ArgumentError.new(
|
179
|
+
'when :provisioned_throughput option is not specified,'\
|
180
|
+
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
181
|
+
)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
145
186
|
def _attribute_definitions
|
146
187
|
_keys.map do |type, attr|
|
147
188
|
{
|
@@ -173,7 +214,7 @@ module Aws
|
|
173
214
|
create_opts[:attribute_definitions] = attr_def
|
174
215
|
end
|
175
216
|
|
176
|
-
def
|
217
|
+
def _add_throughput_to_gsis(global_secondary_indexes, gsi_throughput)
|
177
218
|
missing_throughput = []
|
178
219
|
ret = global_secondary_indexes.map do |params|
|
179
220
|
name = params[:index_name]
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Aws
|
2
2
|
module Record
|
3
3
|
module Transactions
|
4
|
+
extend ClientConfiguration
|
5
|
+
|
4
6
|
class << self
|
5
7
|
|
6
8
|
# @example Usage Example
|
@@ -8,13 +10,13 @@ module Aws
|
|
8
10
|
# include Aws::Record
|
9
11
|
# string_attr :uuid, hash_key: true
|
10
12
|
# end
|
11
|
-
#
|
13
|
+
#
|
12
14
|
# class TableTwo
|
13
15
|
# include Aws::Record
|
14
16
|
# string_attr :hk, hash_key: true
|
15
17
|
# string_attr :rk, range_key: true
|
16
18
|
# end
|
17
|
-
#
|
19
|
+
#
|
18
20
|
# results = Aws::Record::Transactions.transact_find(
|
19
21
|
# transact_items: [
|
20
22
|
# TableOne.tfind_opts(key: { uuid: "uuid1234" }),
|
@@ -93,14 +95,14 @@ module Aws
|
|
93
95
|
# string_attr :uuid, hash_key: true
|
94
96
|
# string_attr :body
|
95
97
|
# end
|
96
|
-
#
|
98
|
+
#
|
97
99
|
# class TableTwo
|
98
100
|
# include Aws::Record
|
99
101
|
# string_attr :hk, hash_key: true
|
100
102
|
# string_attr :rk, range_key: true
|
101
103
|
# string_attr :body
|
102
104
|
# end
|
103
|
-
#
|
105
|
+
#
|
104
106
|
# check_exp = TableOne.transact_check_expression(
|
105
107
|
# key: { uuid: "foo" },
|
106
108
|
# condition_expression: "size(#T) <= :v",
|
@@ -118,7 +120,7 @@ module Aws
|
|
118
120
|
# update_item_2 = TableTwo.find(hk: "hk2", rk: "rk2")
|
119
121
|
# update_item_2.body = "Update!"
|
120
122
|
# delete_item = TableOne.find(uuid: "to_be_deleted")
|
121
|
-
#
|
123
|
+
#
|
122
124
|
# Aws::Record::Transactions.transact_write(
|
123
125
|
# transact_items: [
|
124
126
|
# { check: check_exp },
|
@@ -183,44 +185,6 @@ module Aws
|
|
183
185
|
resp
|
184
186
|
end
|
185
187
|
|
186
|
-
# Configures the Amazon DynamoDB client used by global transaction
|
187
|
-
# operations.
|
188
|
-
#
|
189
|
-
# Please note that this method is also called internally when you first
|
190
|
-
# attempt to perform an operation against the remote end, if you have
|
191
|
-
# not already configured a client. As such, please read and understand
|
192
|
-
# the documentation in the AWS SDK for Ruby V3 around
|
193
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/#Configuration configuration}
|
194
|
-
# to ensure you understand how default configuration behavior works.
|
195
|
-
# When in doubt, call this method to ensure your client is configured
|
196
|
-
# the way you want it to be configured.
|
197
|
-
#
|
198
|
-
# @param [Hash] opts the options you wish to use to create the client.
|
199
|
-
# Note that if you include the option +:client+, all other options
|
200
|
-
# will be ignored. See the documentation for other options in the
|
201
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#initialize-instance_method AWS SDK for Ruby V3}.
|
202
|
-
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in
|
203
|
-
# your own pre-configured client.
|
204
|
-
def configure_client(opts = {})
|
205
|
-
provided_client = opts.delete(:client)
|
206
|
-
opts[:user_agent_suffix] = _user_agent(
|
207
|
-
opts.delete(:user_agent_suffix)
|
208
|
-
)
|
209
|
-
client = provided_client || Aws::DynamoDB::Client.new(opts)
|
210
|
-
@@dynamodb_client = client
|
211
|
-
end
|
212
|
-
|
213
|
-
# Gets the
|
214
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html}
|
215
|
-
# instance that Transactions use. When called for the first time, if
|
216
|
-
# {#configure_client} has not yet been called, will configure a new
|
217
|
-
# client for you with default parameters.
|
218
|
-
#
|
219
|
-
# @return [Aws::DynamoDB::Client] the Amazon DynamoDB client instance.
|
220
|
-
def dynamodb_client
|
221
|
-
@@dynamodb_client ||= configure_client
|
222
|
-
end
|
223
|
-
|
224
188
|
private
|
225
189
|
def _transform_transact_write_items(transact_items, dirty_items, delete_items)
|
226
190
|
transact_items.map do |item|
|
@@ -317,15 +281,6 @@ module Aws
|
|
317
281
|
# check records are a pass-through
|
318
282
|
{ condition_check: opts.merge(check_record) }
|
319
283
|
end
|
320
|
-
|
321
|
-
def _user_agent(custom)
|
322
|
-
if custom
|
323
|
-
custom
|
324
|
-
else
|
325
|
-
" aws-record/#{VERSION}"
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
284
|
end
|
330
285
|
end
|
331
286
|
end
|
data/lib/aws-record/record.rb
CHANGED
@@ -50,7 +50,7 @@ module Aws
|
|
50
50
|
# # Attribute definitions go here...
|
51
51
|
# end
|
52
52
|
def self.included(sub_class)
|
53
|
-
|
53
|
+
sub_class.send(:extend, ClientConfiguration)
|
54
54
|
sub_class.send(:extend, RecordClassMethods)
|
55
55
|
sub_class.send(:include, Attributes)
|
56
56
|
sub_class.send(:include, ItemOperations)
|
@@ -76,12 +76,12 @@ module Aws
|
|
76
76
|
# class MyTable
|
77
77
|
# include Aws::Record
|
78
78
|
# end
|
79
|
-
#
|
79
|
+
#
|
80
80
|
# class MyTableTest
|
81
81
|
# include Aws::Record
|
82
82
|
# set_table_name "test_MyTable"
|
83
83
|
# end
|
84
|
-
#
|
84
|
+
#
|
85
85
|
# MyTable.table_name # => "MyTable"
|
86
86
|
# MyOtherTable.table_name # => "test_MyTable"
|
87
87
|
def table_name
|
@@ -100,12 +100,12 @@ module Aws
|
|
100
100
|
# include Aws::Record
|
101
101
|
# set_table_name "prod_MyTable"
|
102
102
|
# end
|
103
|
-
#
|
103
|
+
#
|
104
104
|
# class MyTableTest
|
105
105
|
# include Aws::Record
|
106
106
|
# set_table_name "test_MyTable"
|
107
107
|
# end
|
108
|
-
#
|
108
|
+
#
|
109
109
|
# MyTable.table_name # => "prod_MyTable"
|
110
110
|
# MyOtherTable.table_name # => "test_MyTable"
|
111
111
|
def set_table_name(name)
|
@@ -148,42 +148,6 @@ module Aws
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
-
# Configures the Amazon DynamoDB client used by this class and all
|
152
|
-
# instances of this class.
|
153
|
-
#
|
154
|
-
# Please note that this method is also called internally when you first
|
155
|
-
# attempt to perform an operation against the remote end, if you have not
|
156
|
-
# already configured a client. As such, please read and understand the
|
157
|
-
# documentation in the AWS SDK for Ruby V2 around
|
158
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/index.html#Configuration configuration}
|
159
|
-
# to ensure you understand how default configuration behavior works. When
|
160
|
-
# in doubt, call this method to ensure your client is configured the way
|
161
|
-
# you want it to be configured.
|
162
|
-
#
|
163
|
-
# @param [Hash] opts the options you wish to use to create the client.
|
164
|
-
# Note that if you include the option +:client+, all other options
|
165
|
-
# will be ignored. See the documentation for other options in the
|
166
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#initialize-instance_method AWS SDK for Ruby V2}.
|
167
|
-
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in your
|
168
|
-
# own pre-configured client.
|
169
|
-
def configure_client(opts = {})
|
170
|
-
provided_client = opts.delete(:client)
|
171
|
-
opts[:user_agent_suffix] = _user_agent(opts.delete(:user_agent_suffix))
|
172
|
-
client = provided_client || Aws::DynamoDB::Client.new(opts)
|
173
|
-
@dynamodb_client = client
|
174
|
-
end
|
175
|
-
|
176
|
-
# Gets the
|
177
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
178
|
-
# instance that this model uses. When called for the first time, if
|
179
|
-
# {#configure_client} has not yet been called, will configure a new client
|
180
|
-
# for you with default parameters.
|
181
|
-
#
|
182
|
-
# @return [Aws::DynamoDB::Client] the Amazon DynamoDB client instance.
|
183
|
-
def dynamodb_client
|
184
|
-
@dynamodb_client ||= configure_client
|
185
|
-
end
|
186
|
-
|
187
151
|
# Turns off mutation tracking for all attributes in the model.
|
188
152
|
def disable_mutation_tracking
|
189
153
|
@track_mutations = false
|
@@ -201,7 +165,11 @@ module Aws
|
|
201
165
|
# @return [Boolean] true if mutation tracking is enabled at the model
|
202
166
|
# level, false otherwise.
|
203
167
|
def mutation_tracking_enabled?
|
204
|
-
@track_mutations
|
168
|
+
if defined?(@track_mutations)
|
169
|
+
@track_mutations
|
170
|
+
else
|
171
|
+
@track_mutations = true
|
172
|
+
end
|
205
173
|
end
|
206
174
|
|
207
175
|
def model_valid?
|
@@ -209,15 +177,6 @@ module Aws
|
|
209
177
|
raise Errors::InvalidModel.new("Table models must include a hash key")
|
210
178
|
end
|
211
179
|
end
|
212
|
-
|
213
|
-
private
|
214
|
-
def _user_agent(custom)
|
215
|
-
if custom
|
216
|
-
custom
|
217
|
-
else
|
218
|
-
" aws-record/#{VERSION}"
|
219
|
-
end
|
220
|
-
end
|
221
180
|
end
|
222
181
|
end
|
223
182
|
end
|
data/lib/aws-record.rb
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
# and limitations under the License.
|
13
13
|
|
14
14
|
require 'aws-sdk-dynamodb'
|
15
|
+
require_relative 'aws-record/record/client_configuration'
|
15
16
|
require_relative 'aws-record/record'
|
16
17
|
require_relative 'aws-record/record/attribute'
|
17
18
|
require_relative 'aws-record/record/attributes'
|
@@ -29,6 +30,8 @@ require_relative 'aws-record/record/table_migration'
|
|
29
30
|
require_relative 'aws-record/record/version'
|
30
31
|
require_relative 'aws-record/record/transactions'
|
31
32
|
require_relative 'aws-record/record/buildable_search'
|
33
|
+
require_relative 'aws-record/record/batch_write'
|
34
|
+
require_relative 'aws-record/record/batch'
|
32
35
|
require_relative 'aws-record/record/marshalers/string_marshaler'
|
33
36
|
require_relative 'aws-record/record/marshalers/boolean_marshaler'
|
34
37
|
require_relative 'aws-record/record/marshalers/integer_marshaler'
|
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: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amazon Web Services
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-dynamodb
|
@@ -26,7 +26,8 @@ dependencies:
|
|
26
26
|
version: '1.18'
|
27
27
|
description: Provides an object mapping abstraction for Amazon DynamoDB.
|
28
28
|
email:
|
29
|
-
-
|
29
|
+
- mamuller@amazon.com
|
30
|
+
- alexwoo@amazon.com
|
30
31
|
executables: []
|
31
32
|
extensions: []
|
32
33
|
extra_rdoc_files: []
|
@@ -35,7 +36,10 @@ files:
|
|
35
36
|
- lib/aws-record/record.rb
|
36
37
|
- lib/aws-record/record/attribute.rb
|
37
38
|
- lib/aws-record/record/attributes.rb
|
39
|
+
- lib/aws-record/record/batch.rb
|
40
|
+
- lib/aws-record/record/batch_write.rb
|
38
41
|
- lib/aws-record/record/buildable_search.rb
|
42
|
+
- lib/aws-record/record/client_configuration.rb
|
39
43
|
- lib/aws-record/record/dirty_tracking.rb
|
40
44
|
- lib/aws-record/record/errors.rb
|
41
45
|
- lib/aws-record/record/item_collection.rb
|
@@ -65,7 +69,7 @@ homepage: http://github.com/aws/aws-sdk-ruby-record
|
|
65
69
|
licenses:
|
66
70
|
- Apache 2.0
|
67
71
|
metadata: {}
|
68
|
-
post_install_message:
|
72
|
+
post_install_message:
|
69
73
|
rdoc_options: []
|
70
74
|
require_paths:
|
71
75
|
- lib
|
@@ -80,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
84
|
- !ruby/object:Gem::Version
|
81
85
|
version: '0'
|
82
86
|
requirements: []
|
83
|
-
rubygems_version: 3.
|
84
|
-
signing_key:
|
87
|
+
rubygems_version: 3.2.7
|
88
|
+
signing_key:
|
85
89
|
specification_version: 4
|
86
90
|
summary: AWS Record library for Amazon DynamoDB
|
87
91
|
test_files: []
|