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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d017802e3f3023427a79e39fe59468a66f1fe138ef3a6bd173bdcc4d4a15c05c
4
- data.tar.gz: c9efe98e3226977a5c381d16cf0dd9ffcd77e6c99d7d4407d58c2e20908c5be2
3
+ metadata.gz: 67f48531ca8b917f680a1d9a5d21afd1611aba0eb96916a5783addaf7939cda8
4
+ data.tar.gz: 7f6cbb16271455ada17a61f32106800b65d3b4103a5254e7686e06d5cf715cca
5
5
  SHA512:
6
- metadata.gz: 0fd56a56605143708ee9f70074317452105860f86835f59653e484c0b1f700b9a7e587383fb9a9278c1eb3c0585cb6fde1024d07bf3d6bcefc1497fcd9ab5984
7
- data.tar.gz: ba3f5889ca0954c294ca77b752ab45cb7151067c81369b3b303c86f72e32bc2f0eb7496ca6ccdfbfbf515ef6d04c1809cf32f839cc3574d35ff1f965646505a9
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
- unless dv.nil?
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(statement_str, subs, values)
106
- @params[:key_condition_expression] = statement_str
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(statement_str, subs, values)
140
- @params[:filter_expression] = statement_str
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] = statement_str
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!(/:(\w+)/) do |match|
192
- key = match.gsub!(':','').to_sym
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!(/[?]/) do |match|
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
- unless count == subs.size
215
- raise "Expected #{count} values in the substitution set, but found #{subs.size}"
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
- record = model.new
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
- model.attributes.attributes.each do |name, attr|
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
- # Deletes the item instance that matches the key values of this item
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] :provisioned_throughput This is a required argument,
60
- # in which you must specify the +:read_capacity_units+ and
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. It should map your
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
- "If you define global secondary indexes, you must also define"\
81
- " :global_secondary_index_throughput on table creation."
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
- gsis_with_throughput = _add_throughout_to_gsis(gsis, gsit)
85
- create_opts[:global_secondary_indexes] = gsis_with_throughput
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 _add_throughout_to_gsis(global_secondary_indexes, gsi_throughput)
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
@@ -13,6 +13,6 @@
13
13
 
14
14
  module Aws
15
15
  module Record
16
- VERSION = '2.4.0'
16
+ VERSION = '2.7.0'
17
17
  end
18
18
  end
@@ -50,7 +50,7 @@ module Aws
50
50
  # # Attribute definitions go here...
51
51
  # end
52
52
  def self.included(sub_class)
53
- @track_mutations = true
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 == false ? false : true
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.1
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: 2020-05-29 00:00:00.000000000 Z
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
- - alexwood@amazon.com
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.0.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: []