aws-record 2.4.0 → 2.6.1

Sign up to get free protection for your applications and to get access to all the features.
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: []