aws-record 2.4.0 → 2.6.1

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
- SHA1:
3
- metadata.gz: c0d7d527489fd1a7848279570aefbe37aeee9297
4
- data.tar.gz: f3234598e3f895c93184a7b283a7064853ad3707
2
+ SHA256:
3
+ metadata.gz: 613ebc2bb79fb30645f69fc831911f4fb269e9fe1e0d69bb064e5cc0b6c3294c
4
+ data.tar.gz: 6012bd27fd72dd5b8702e9833d302c57df7d9c44834ac37a6f347735328898ff
5
5
  SHA512:
6
- metadata.gz: afd2c0b89fac562aeaee2fb0f67f25cee31700b29639e52a8281babd769a45b8da8bf2cedf86d396904e1103b4f9e2722445a13bada7cab446c443b460b8e42b
7
- data.tar.gz: f0dfc0620149bbf63d2b5334dc441f2370e220278a3893f5b84b1e68a6a74acfcfec9f36e67cb4d31696add5e4795a567a4444d4b05f685dcbfbe8dbfbe0df98
6
+ metadata.gz: e524df13f1433045d958466a377672f28a9c5cb7765f1d365ba856ff51ad8b78d7ab60bf55bd4b36d36ed4d880f7452ee5f09aff9cf0f7ec67f1096dbb3ccc2a
7
+ data.tar.gz: 34bb9db197f9f6b825b1b4296aace9df35f1e72f9e814bc530b25e36117500ab52b2710730ebf3dd712381fb7d85415f36a52a61c1c32420922492d3ebf21729
@@ -50,7 +50,6 @@ module Aws
50
50
  # # Attribute definitions go here...
51
51
  # end
52
52
  def self.included(sub_class)
53
- @track_mutations = true
54
53
  sub_class.send(:extend, RecordClassMethods)
55
54
  sub_class.send(:include, Attributes)
56
55
  sub_class.send(:include, ItemOperations)
@@ -201,7 +200,11 @@ module Aws
201
200
  # @return [Boolean] true if mutation tracking is enabled at the model
202
201
  # level, false otherwise.
203
202
  def mutation_tracking_enabled?
204
- @track_mutations == false ? false : true
203
+ if defined?(@track_mutations)
204
+ @track_mutations
205
+ else
206
+ @track_mutations = true
207
+ end
205
208
  end
206
209
 
207
210
  def model_valid?
@@ -48,12 +48,12 @@ module Aws
48
48
  # item is nil or not set at persistence time.
49
49
  def initialize(name, options = {})
50
50
  @name = name
51
- @database_name = options[:database_attribute_name] || name.to_s
51
+ @database_name = (options[:database_attribute_name] || name).to_s
52
52
  @dynamodb_type = options[:dynamodb_type]
53
53
  @marshaler = options[:marshaler] || DefaultMarshaler
54
54
  @persist_nil = options[:persist_nil]
55
55
  dv = options[:default_value]
56
- @default_value_or_lambda = type_cast(dv) unless dv.nil?
56
+ @default_value_or_lambda = _is_lambda?(dv) ? dv : type_cast(dv)
57
57
  end
58
58
 
59
59
  # Attempts to type cast a raw value into the attribute's type. This call
@@ -92,8 +92,8 @@ module Aws
92
92
 
93
93
  # @api private
94
94
  def default_value
95
- if @default_value_or_lambda.respond_to?(:call)
96
- @default_value_or_lambda.call
95
+ if _is_lambda?(@default_value_or_lambda)
96
+ type_cast(@default_value_or_lambda.call)
97
97
  else
98
98
  _deep_copy(@default_value_or_lambda)
99
99
  end
@@ -104,6 +104,10 @@ module Aws
104
104
  Marshal.load(Marshal.dump(obj))
105
105
  end
106
106
 
107
+ def _is_lambda?(obj)
108
+ obj.respond_to?(:call)
109
+ end
110
+
107
111
  end
108
112
 
109
113
  # This is an identity marshaler, which performs no changes for type casting
@@ -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
 
@@ -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!
@@ -122,9 +122,9 @@ module Aws
122
122
 
123
123
  def populate_default_values
124
124
  @model_attributes.attributes.each do |name, attribute|
125
- unless attribute.default_value.nil?
125
+ unless (default_value = attribute.default_value).nil?
126
126
  if @data[name].nil? && @data[name].nil?
127
- @data[name] = attribute.default_value
127
+ @data[name] = default_value
128
128
  end
129
129
  end
130
130
  end
@@ -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
@@ -58,7 +58,7 @@ module Aws
58
58
  if item.is_a?(Numeric)
59
59
  item
60
60
  else
61
- BigDecimal.new(item.to_s)
61
+ BigDecimal(item.to_s)
62
62
  end
63
63
  end
64
64
  end
@@ -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]
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.0
4
+ version: 2.6.1
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: 2019-07-16 00:00:00.000000000 Z
11
+ date: 2021-08-10 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: []
@@ -65,7 +66,7 @@ homepage: http://github.com/aws/aws-sdk-ruby-record
65
66
  licenses:
66
67
  - Apache 2.0
67
68
  metadata: {}
68
- post_install_message:
69
+ post_install_message:
69
70
  rdoc_options: []
70
71
  require_paths:
71
72
  - lib
@@ -80,9 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
81
  - !ruby/object:Gem::Version
81
82
  version: '0'
82
83
  requirements: []
83
- rubyforge_project:
84
- rubygems_version: 2.5.2
85
- signing_key:
84
+ rubygems_version: 3.2.7
85
+ signing_key:
86
86
  specification_version: 4
87
87
  summary: AWS Record library for Amazon DynamoDB
88
88
  test_files: []