aws-record 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +335 -0
  3. data/LICENSE +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-record/record/attribute.rb +9 -21
  6. data/lib/aws-record/record/attributes.rb +68 -78
  7. data/lib/aws-record/record/batch.rb +13 -12
  8. data/lib/aws-record/record/batch_read.rb +5 -2
  9. data/lib/aws-record/record/batch_write.rb +1 -12
  10. data/lib/aws-record/record/buildable_search.rb +33 -28
  11. data/lib/aws-record/record/client_configuration.rb +10 -21
  12. data/lib/aws-record/record/dirty_tracking.rb +30 -44
  13. data/lib/aws-record/record/errors.rb +1 -13
  14. data/lib/aws-record/record/item_collection.rb +5 -16
  15. data/lib/aws-record/record/item_data.rb +4 -18
  16. data/lib/aws-record/record/item_operations.rb +86 -93
  17. data/lib/aws-record/record/key_attributes.rb +1 -14
  18. data/lib/aws-record/record/marshalers/boolean_marshaler.rb +2 -16
  19. data/lib/aws-record/record/marshalers/date_marshaler.rb +1 -15
  20. data/lib/aws-record/record/marshalers/date_time_marshaler.rb +2 -14
  21. data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +1 -14
  22. data/lib/aws-record/record/marshalers/float_marshaler.rb +3 -19
  23. data/lib/aws-record/record/marshalers/integer_marshaler.rb +3 -19
  24. data/lib/aws-record/record/marshalers/list_marshaler.rb +2 -16
  25. data/lib/aws-record/record/marshalers/map_marshaler.rb +2 -16
  26. data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +3 -16
  27. data/lib/aws-record/record/marshalers/string_marshaler.rb +2 -16
  28. data/lib/aws-record/record/marshalers/string_set_marshaler.rb +3 -16
  29. data/lib/aws-record/record/marshalers/time_marshaler.rb +1 -14
  30. data/lib/aws-record/record/model_attributes.rb +14 -35
  31. data/lib/aws-record/record/query.rb +7 -21
  32. data/lib/aws-record/record/secondary_indexes.rb +23 -42
  33. data/lib/aws-record/record/table_config.rb +52 -74
  34. data/lib/aws-record/record/table_migration.rb +43 -66
  35. data/lib/aws-record/record/transactions.rb +67 -38
  36. data/lib/aws-record/record/version.rb +2 -13
  37. data/lib/aws-record/record.rb +30 -49
  38. metadata +14 -5
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws
2
4
  module Record
3
5
  module Transactions
4
6
  extend ClientConfiguration
5
7
 
6
8
  class << self
7
-
8
9
  # @example Usage Example
9
10
  # class TableOne
10
11
  # include Aws::Record
@@ -26,15 +27,26 @@ module Aws
26
27
  # ) # => results.responses contains nil or marshalled items
27
28
  # results.responses.map { |r| r.class } # [TableOne, TableTwo, TableTwo]
28
29
  #
29
- # Provides a way to run a transactional find across multiple DynamoDB
30
+ # Provides support for the
31
+ # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_get_items-instance_method
32
+ # Aws::DynamoDB::Client#transact_get_item} for aws-record models.
33
+ #
34
+ # This method runs a transactional find across multiple DynamoDB
30
35
  # items, including transactions which get items across multiple actual
31
- # or virtual tables.
36
+ # or virtual tables. This call can contain up to 100 item keys.
37
+ #
38
+ # DynamoDB will reject the request if any of the following is true:
39
+ # * A conflicting operation is in the process of updating an item to be read.
40
+ # * There is insufficient provisioned capacity for the transaction to be completed.
41
+ # * There is a user error, such as an invalid data format.
42
+ # * The aggregate size of the items in the transaction cannot exceed 4 MB.
32
43
  #
33
44
  # @param [Hash] opts Options to pass through to
34
- # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_get_items-instance_method Aws::DynamoDB::Client#transact_get_items},
35
- # with the exception of the :transact_items array, which uses the
36
- # +#tfind_opts+ operation on your model class to provide extra
37
- # metadata used to marshal your items after retrieval.
45
+ # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_get_items-instance_method
46
+ # Aws::DynamoDB::Client#transact_get_items}, with the exception of the
47
+ # +:transact_items+ array, which uses the {ItemOperations.ItemOperationsClassMethods.tfind_opts #tfind_opts}
48
+ # operation on your model class to provide extra metadata
49
+ # used to marshal your items after retrieval.
38
50
  # @option opts [Array] :transact_items A set of +#tfind_opts+ results,
39
51
  # such as those created by the usage example.
40
52
  # @option opts [Aws::DynamoDB::Client] :client Optionally, you can pass
@@ -58,7 +70,6 @@ module Aws
58
70
  client_resp = client.transact_get_items(
59
71
  request_opts
60
72
  )
61
- responses = client_resp.responses
62
73
  index = -1
63
74
  ret = OpenStruct.new
64
75
  ret.consumed_capacity = client_resp.consumed_capacity
@@ -137,7 +148,11 @@ module Aws
137
148
  # ]
138
149
  # )
139
150
  #
140
- # Provides a way to pass in aws-record items into transactional writes,
151
+ # Provides support for the
152
+ # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_write_items-instance_method
153
+ # Aws::DynamoDB::Client#transact_write_items} for aws-record models.
154
+ #
155
+ # This method passes in aws-record items into transactional writes,
141
156
  # as well as adding the ability to run 'save' commands in a transaction
142
157
  # while allowing aws-record to determine if a :put or :update operation
143
158
  # is most appropriate. +#transact_write+ supports 5 different transact
@@ -145,7 +160,7 @@ module Aws
145
160
  # - save: Behaves much like the +#save+ operation on the item itself.
146
161
  # If the keys are dirty, and thus it appears to be a new item, will
147
162
  # create a :put operation with a conditional check on the item's
148
- # existance. Note that you cannot bring your own conditional
163
+ # existence. Note that you cannot bring your own conditional
149
164
  # expression in this case. If you wish to force put or add your
150
165
  # own conditional checks, use the :put operation.
151
166
  # - put: Does a force put for the given item key and model.
@@ -153,13 +168,28 @@ module Aws
153
168
  # - delete: Deletes the given item.
154
169
  # - check: Takes the result of +#transact_check_expression+,
155
170
  # performing the specified check as a part of the transaction.
171
+ # See {ItemOperations.ItemOperationsClassMethods.transact_check_expression #transact_check_expression}
172
+ # for more information.
173
+ #
174
+ # This call contain up to 100 action requests.
175
+ #
176
+ # DynamoDB will reject the request if any of the following is true:
177
+ # * A condition in one of the condition expressions is not met.
178
+ # * An ongoing operation is in the process of updating the same item.
179
+ # * There is insufficient provisioned capacity for the transaction to
180
+ # be completed.
181
+ # * An item size becomes too large (bigger than 400 KB), a local secondary
182
+ # index (LSI) becomes too large, or a similar validation error occurs
183
+ # because of changes made by the transaction.
184
+ # * The aggregate size of the items in the transaction exceeds 4 MB.
185
+ # * There is a user error, such as an invalid data format.
156
186
  #
157
187
  # @param [Hash] opts Options to pass through to
158
- # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_write_items-instance_method Aws::DynamoDB::Client#transact_write_items}
159
- # with the exception of :transact_items array, which is transformed
160
- # to use your item to populate the :key, :table_name, :item, and/or
161
- # :update_expression parameters as appropriate. See the usage example
162
- # for a comprehensive set of combinations.
188
+ # {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#transact_write_items-instance_method
189
+ # Aws::DynamoDB::Client#transact_write_items} with the exception of
190
+ # :transact_items array, which is transformed to use your item to populate
191
+ # the :key, :table_name, :item, and/or :update_expression parameters
192
+ # as appropriate. See the usage example for a comprehensive set of combinations.
163
193
  # @option opts [Array] :transact_items An array of hashes, accepting
164
194
  # +:save+, +:put+, +:delete+, +:update+, and +:check+ as specified.
165
195
  # @option opts [Aws::DynamoDB::Client] :client Optionally, you can
@@ -180,35 +210,35 @@ module Aws
180
210
  opts[:transact_items] = transact_items
181
211
  resp = client.transact_write_items(opts)
182
212
  # mark all items clean/destroyed as needed if we didn't raise an exception
183
- dirty_items.each { |i| i.clean! }
184
- delete_items.each { |i| i.instance_variable_get("@data").destroyed = true }
213
+ dirty_items.each(&:clean!)
214
+ delete_items.each { |i| i.instance_variable_get('@data').destroyed = true }
185
215
  resp
186
216
  end
187
217
 
188
218
  private
219
+
189
220
  def _transform_transact_write_items(transact_items, dirty_items, delete_items)
190
221
  transact_items.map do |item|
191
222
  # this code will assume users only provided one operation, and
192
223
  # will fail down the line if that assumption is wrong
193
- if save_record = item.delete(:save)
224
+ if (save_record = item.delete(:save))
194
225
  dirty_items << save_record
195
226
  _transform_save_record(save_record, item)
196
- elsif put_record = item.delete(:put)
227
+ elsif (put_record = item.delete(:put))
197
228
  dirty_items << put_record
198
229
  _transform_put_record(put_record, item)
199
- elsif delete_record = item.delete(:delete)
230
+ elsif (delete_record = item.delete(:delete))
200
231
  delete_items << delete_record
201
232
  _transform_delete_record(delete_record, item)
202
- elsif update_record = item.delete(:update)
233
+ elsif (update_record = item.delete(:update))
203
234
  dirty_items << update_record
204
235
  _transform_update_record(update_record, item)
205
- elsif check_record = item.delete(:check)
236
+ elsif (check_record = item.delete(:check))
206
237
  _transform_check_record(check_record, item)
207
238
  else
208
- raise ArgumentError.new(
209
- "Invalid transact write item, must include an operation of "\
210
- "type :save, :update, :delete, :update, or :check - #{item}"
211
- )
239
+ raise ArgumentError, 'Invalid transact write item, must include an operation of '\
240
+ "type :save, :update, :delete, :update, or :check - #{item}"
241
+
212
242
  end
213
243
  end
214
244
  end
@@ -219,16 +249,15 @@ module Aws
219
249
  if save_record.send(:expect_new_item?)
220
250
  safety_expression = save_record.send(:prevent_overwrite_expression)
221
251
  if opts.include?(:condition_expression)
222
- raise Errors::TransactionalSaveConditionCollision.new(
223
- "Transactional write includes a :save operation that would "\
224
- "result in a 'safe put' for the given item, yet a "\
225
- "condition expression was also provided. This is not "\
226
- "currently supported. You should rewrite this case to use "\
227
- "a :put transaction, adding the existence check to your "\
228
- "own condition expression if desired.\n"\
229
- "\tItem: #{JSON.pretty_unparse(save_record.to_h)}\n"\
230
- "\tExtra Options: #{JSON.pretty_unparse(opts)}"
231
- )
252
+ raise Errors::TransactionalSaveConditionCollision,
253
+ 'Transactional write includes a :save operation that would '\
254
+ "result in a 'safe put' for the given item, yet a "\
255
+ 'condition expression was also provided. This is not '\
256
+ 'currently supported. You should rewrite this case to use '\
257
+ 'a :put transaction, adding the existence check to your '\
258
+ "own condition expression if desired.\n"\
259
+ "\tItem: #{JSON.pretty_unparse(save_record.to_h)}\n"\
260
+ "\tExtra Options: #{JSON.pretty_unparse(opts)}"
232
261
  else
233
262
  opts = opts.merge(safety_expression)
234
263
  _transform_put_record(save_record, opts)
@@ -264,12 +293,12 @@ module Aws
264
293
  opts[:key] = update_record.send(:key_values)
265
294
  opts[:update_expression] = uex
266
295
  # need to combine expression attribute names and values
267
- if names = opts[:expression_attribute_names]
296
+ if (names = opts[:expression_attribute_names])
268
297
  opts[:expression_attribute_names] = exp_attr_names.merge(names)
269
298
  else
270
299
  opts[:expression_attribute_names] = exp_attr_names
271
300
  end
272
- if values = opts[:expression_attribute_values]
301
+ if (values = opts[:expression_attribute_values])
273
302
  opts[:expression_attribute_values] = exp_attr_values.merge(values)
274
303
  else
275
304
  opts[:expression_attribute_values] = exp_attr_values
@@ -1,18 +1,7 @@
1
- # Copyright 2015-2017 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.
1
+ # frozen_string_literal: true
13
2
 
14
3
  module Aws
15
4
  module Record
16
- VERSION = '2.7.0'
5
+ VERSION = File.read(File.expand_path('../../../../VERSION', __FILE__)).strip
17
6
  end
18
7
  end
@@ -1,18 +1,6 @@
1
- # Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You may not
4
- # use this file except in compliance with the License. A copy of the License is
5
- # located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is distributed on
10
- # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
- # or implied. See the License for the specific language governing permissions
12
- # and limitations under the License.
1
+ # frozen_string_literal: true
13
2
 
14
3
  module Aws
15
-
16
4
  # +Aws::Record+ is the module you include in your model classes in order to
17
5
  # decorate them with the Amazon DynamoDB integration methods provided by this
18
6
  # library. Methods you can use are shown below, in sub-modules organized by
@@ -84,9 +72,7 @@ module Aws
84
72
  sub_class.send(:include, DirtyTracking)
85
73
  sub_class.send(:include, Query)
86
74
  sub_class.send(:include, SecondaryIndexes)
87
- if Aws::Record.extends_record?(sub_class)
88
- inherit_track_mutations(sub_class)
89
- end
75
+ inherit_track_mutations(sub_class) if Aws::Record.extends_record?(sub_class)
90
76
  end
91
77
 
92
78
  # @api private
@@ -94,18 +80,21 @@ module Aws
94
80
  klass.superclass.include?(Aws::Record)
95
81
  end
96
82
 
83
+ # @api private
84
+ def self.inherit_track_mutations(klass)
85
+ superclass_track_mutations = klass.superclass.instance_variable_get('@track_mutations')
86
+ klass.instance_variable_set('@track_mutations', superclass_track_mutations)
87
+ end
88
+
89
+ private_class_method :inherit_track_mutations
90
+
97
91
  private
92
+
98
93
  def dynamodb_client
99
94
  self.class.dynamodb_client
100
95
  end
101
96
 
102
- def self.inherit_track_mutations(klass)
103
- superclass_track_mutations = klass.superclass.instance_variable_get("@track_mutations")
104
- klass.instance_variable_set("@track_mutations", superclass_track_mutations)
105
- end
106
-
107
97
  module RecordClassMethods
108
-
109
98
  # Returns the Amazon DynamoDB table name for this model class.
110
99
  #
111
100
  # By default, this will simply be the name of the class. However, you can
@@ -127,14 +116,16 @@ module Aws
127
116
  # MyTable.table_name # => "MyTable"
128
117
  # MyOtherTable.table_name # => "test_MyTable"
129
118
  def table_name
119
+ # rubocop:disable Style/RedundantSelf
130
120
  @table_name ||= begin
131
121
  if Aws::Record.extends_record?(self) &&
132
- default_table_name(self.superclass) != self.superclass.table_name
122
+ default_table_name(self.superclass) != self.superclass.table_name
133
123
  self.superclass.instance_variable_get('@table_name')
134
124
  else
135
125
  default_table_name(self)
136
126
  end
137
127
  end
128
+ # rubocop:enable Style/RedundantSelf
138
129
  end
139
130
 
140
131
  # Allows you to set a custom Amazon DynamoDB table name for this model
@@ -186,7 +177,7 @@ module Aws
186
177
  # end
187
178
  #
188
179
  # Dog.table_name # => "DogTable"
189
- def set_table_name(name)
180
+ def set_table_name(name) # rubocop:disable Naming/AccessorMethodName
190
181
  @table_name = name
191
182
  end
192
183
 
@@ -198,32 +189,24 @@ module Aws
198
189
  # @raise [Aws::Record::Errors::TableDoesNotExist] if the table name does
199
190
  # not exist in DynamoDB.
200
191
  def provisioned_throughput
201
- begin
202
- resp = dynamodb_client.describe_table(table_name: table_name)
203
- throughput = resp.table.provisioned_throughput
204
- return {
205
- read_capacity_units: throughput.read_capacity_units,
206
- write_capacity_units: throughput.write_capacity_units
207
- }
208
- rescue DynamoDB::Errors::ResourceNotFoundException
209
- raise Record::Errors::TableDoesNotExist
210
- end
192
+ resp = dynamodb_client.describe_table(table_name: table_name)
193
+ throughput = resp.table.provisioned_throughput
194
+ {
195
+ read_capacity_units: throughput.read_capacity_units,
196
+ write_capacity_units: throughput.write_capacity_units
197
+ }
198
+ rescue DynamoDB::Errors::ResourceNotFoundException
199
+ raise Record::Errors::TableDoesNotExist
211
200
  end
212
201
 
213
202
  # Checks if the model's table name exists in Amazon DynamoDB.
214
203
  #
215
204
  # @return [Boolean] true if the table does exist, false if it does not.
216
205
  def table_exists?
217
- begin
218
- resp = dynamodb_client.describe_table(table_name: table_name)
219
- if resp.table.table_status == "ACTIVE"
220
- true
221
- else
222
- false
223
- end
224
- rescue DynamoDB::Errors::ResourceNotFoundException
225
- false
226
- end
206
+ resp = dynamodb_client.describe_table(table_name: table_name)
207
+ resp.table.table_status == 'ACTIVE'
208
+ rescue DynamoDB::Errors::ResourceNotFoundException
209
+ false
227
210
  end
228
211
 
229
212
  # Turns off mutation tracking for all attributes in the model.
@@ -257,17 +240,15 @@ module Aws
257
240
  end
258
241
 
259
242
  def model_valid?
260
- if @keys.hash_key.nil?
261
- raise Errors::InvalidModel.new("Table models must include a hash key")
262
- end
243
+ raise Errors::InvalidModel, 'Table models must include a hash key' if @keys.hash_key.nil?
263
244
  end
264
245
 
265
246
  private
247
+
266
248
  def default_table_name(klass)
267
249
  return unless klass.name
268
- klass.name.split("::").join("_")
250
+ klass.name.split('::').join('_')
269
251
  end
270
-
271
252
  end
272
253
  end
273
254
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.0
4
+ version: 2.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amazon Web Services
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-13 00:00:00.000000000 Z
11
+ date: 2023-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.18'
19
+ version: '1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.85.0
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '1.18'
29
+ version: '1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.85.0
27
33
  description: Provides an object mapping abstraction for Amazon DynamoDB.
28
34
  email:
29
35
  - mamuller@amazon.com
@@ -32,6 +38,9 @@ executables: []
32
38
  extensions: []
33
39
  extra_rdoc_files: []
34
40
  files:
41
+ - CHANGELOG.md
42
+ - LICENSE
43
+ - VERSION
35
44
  - lib/aws-record.rb
36
45
  - lib/aws-record/record.rb
37
46
  - lib/aws-record/record/attribute.rb
@@ -85,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
94
  - !ruby/object:Gem::Version
86
95
  version: '0'
87
96
  requirements: []
88
- rubygems_version: 3.3.3
97
+ rubygems_version: 3.4.10
89
98
  signing_key:
90
99
  specification_version: 4
91
100
  summary: AWS Record library for Amazon DynamoDB