aws-record 2.11.0 → 2.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +78 -19
- data/VERSION +1 -1
- data/lib/aws-record/record/attribute.rb +4 -2
- data/lib/aws-record/record/batch_read.rb +8 -13
- data/lib/aws-record/record/batch_write.rb +2 -1
- data/lib/aws-record/record/buildable_search.rb +15 -20
- data/lib/aws-record/record/client_configuration.rb +7 -7
- data/lib/aws-record/record/dirty_tracking.rb +3 -11
- data/lib/aws-record/record/errors.rb +11 -1
- data/lib/aws-record/record/item_collection.rb +5 -5
- data/lib/aws-record/record/item_data.rb +10 -11
- data/lib/aws-record/record/item_operations.rb +98 -70
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +4 -4
- data/lib/aws-record/record/marshalers/date_marshaler.rb +1 -3
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +1 -3
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +2 -6
- data/lib/aws-record/record/marshalers/float_marshaler.rb +4 -4
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +4 -4
- data/lib/aws-record/record/marshalers/list_marshaler.rb +6 -6
- data/lib/aws-record/record/marshalers/map_marshaler.rb +6 -6
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +7 -7
- data/lib/aws-record/record/marshalers/string_marshaler.rb +3 -1
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +6 -6
- data/lib/aws-record/record/marshalers/time_marshaler.rb +1 -3
- data/lib/aws-record/record/model_attributes.rb +14 -16
- data/lib/aws-record/record/query.rb +4 -4
- data/lib/aws-record/record/secondary_indexes.rb +22 -25
- data/lib/aws-record/record/table_config.rb +45 -56
- data/lib/aws-record/record/table_migration.rb +32 -36
- data/lib/aws-record/record/transactions.rb +18 -18
- data/lib/aws-record/record/version.rb +1 -1
- data/lib/aws-record/record.rb +8 -8
- metadata +4 -5
@@ -52,31 +52,29 @@ module Aws
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def _validate_attr_name(name)
|
55
|
-
unless name.is_a?(Symbol)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
raise Errors::NameCollision, "Cannot overwrite existing attribute #{name}"
|
60
|
-
end
|
55
|
+
raise ArgumentError, 'Must use symbolized :name attribute.' unless name.is_a?(Symbol)
|
56
|
+
return unless @attributes[name]
|
57
|
+
|
58
|
+
raise Errors::NameCollision, "Cannot overwrite existing attribute #{name}"
|
61
59
|
end
|
62
60
|
|
63
61
|
def _check_if_reserved(name)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
return unless @model_class.instance_methods.include?(name)
|
63
|
+
|
64
|
+
raise Errors::ReservedName, "Cannot name an attribute #{name}, that would collide with an " \
|
65
|
+
'existing instance method.'
|
68
66
|
end
|
69
67
|
|
70
68
|
def _check_for_naming_collisions(name, storage_name)
|
71
69
|
if @attributes[storage_name.to_sym]
|
72
|
-
raise Errors::NameCollision, "Custom storage name #{storage_name} already exists as an"\
|
73
|
-
"
|
70
|
+
raise Errors::NameCollision, "Custom storage name #{storage_name} already exists as an " \
|
71
|
+
"attribute name in #{@attributes}"
|
74
72
|
elsif @storage_attributes[name.to_s]
|
75
|
-
raise Errors::NameCollision, "Attribute name #{name} already exists as a custom storage"\
|
76
|
-
"
|
73
|
+
raise Errors::NameCollision, "Attribute name #{name} already exists as a custom storage " \
|
74
|
+
"name in #{@storage_attributes}"
|
77
75
|
elsif @storage_attributes[storage_name]
|
78
|
-
raise Errors::NameCollision, "Custom storage name #{storage_name} already in use in"\
|
79
|
-
"
|
76
|
+
raise Errors::NameCollision, "Custom storage name #{storage_name} already in use in " \
|
77
|
+
"#{@storage_attributes}"
|
80
78
|
|
81
79
|
end
|
82
80
|
end
|
@@ -10,7 +10,7 @@ module Aws
|
|
10
10
|
|
11
11
|
module QueryClassMethods
|
12
12
|
# This method calls
|
13
|
-
# {http://docs.aws.amazon.com/
|
13
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#query-instance_method
|
14
14
|
# Aws::DynamoDB::Client#query}, populating the +:table_name+ parameter from the model
|
15
15
|
# class, and combining this with the other parameters you provide.
|
16
16
|
#
|
@@ -44,7 +44,7 @@ module Aws
|
|
44
44
|
# end
|
45
45
|
#
|
46
46
|
# @param [Hash] opts options to pass on to the client call to +#query+.
|
47
|
-
# See the documentation above in the AWS SDK for Ruby
|
47
|
+
# See the documentation above in the AWS SDK for Ruby V3.
|
48
48
|
# @return [Aws::Record::ItemCollection] an enumerable collection of the
|
49
49
|
# query result.
|
50
50
|
def query(opts)
|
@@ -53,7 +53,7 @@ module Aws
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# This method calls
|
56
|
-
# {http://docs.aws.amazon.com/
|
56
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#scan-instance_method
|
57
57
|
# Aws::DynamoDB::Client#scan}, populating the +:table_name+ parameter from the model
|
58
58
|
# class, and combining this with the other parameters you provide.
|
59
59
|
#
|
@@ -82,7 +82,7 @@ module Aws
|
|
82
82
|
# end
|
83
83
|
#
|
84
84
|
# @param [Hash] opts options to pass on to the client call to +#scan+.
|
85
|
-
# See the documentation above in the AWS SDK for Ruby
|
85
|
+
# See the documentation above in the AWS SDK for Ruby V3.
|
86
86
|
# @return [Aws::Record::ItemCollection] an enumerable collection of the
|
87
87
|
# scan result.
|
88
88
|
def scan(opts = {})
|
@@ -30,11 +30,11 @@ module Aws
|
|
30
30
|
# @param [Symbol] name index name for this local secondary index
|
31
31
|
# @param [Hash] opts
|
32
32
|
# @option opts [Symbol] :range_key the range key used by this local
|
33
|
-
#
|
34
|
-
#
|
33
|
+
# secondary index. Note that the hash key MUST be the table's hash
|
34
|
+
# key, and so that value will be filled in for you.
|
35
35
|
# @option opts [Hash] :projection a hash which defines which attributes
|
36
|
-
#
|
37
|
-
#
|
36
|
+
# are copied from the table to the index. See shape details in the
|
37
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Types/Projection.html AWS SDK for Ruby V3 docs}.
|
38
38
|
def local_secondary_index(name, opts)
|
39
39
|
opts[:hash_key] = hash_key
|
40
40
|
_validate_required_lsi_keys(opts)
|
@@ -50,12 +50,12 @@ module Aws
|
|
50
50
|
# @param [Symbol] name index name for this global secondary index
|
51
51
|
# @param [Hash] opts
|
52
52
|
# @option opts [Symbol] :hash_key the hash key used by this global
|
53
|
-
#
|
53
|
+
# secondary index.
|
54
54
|
# @option opts [Symbol] :range_key the range key used by this global
|
55
|
-
#
|
55
|
+
# secondary index.
|
56
56
|
# @option opts [Hash] :projection a hash which defines which attributes
|
57
|
-
#
|
58
|
-
#
|
57
|
+
# are copied from the table to the index. See shape details in the
|
58
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Types/Projection.html AWS SDK for Ruby V3 docs}.
|
59
59
|
def global_secondary_index(name, opts)
|
60
60
|
_validate_required_gsi_keys(opts)
|
61
61
|
global_secondary_indexes[name] = opts
|
@@ -99,7 +99,8 @@ module Aws
|
|
99
99
|
|
100
100
|
def _migration_format_indexes(indexes)
|
101
101
|
return nil if indexes.empty?
|
102
|
-
|
102
|
+
|
103
|
+
indexes.collect do |name, opts|
|
103
104
|
h = { index_name: name }
|
104
105
|
h[:key_schema] = _si_key_schema(opts)
|
105
106
|
hk = opts.delete(:hash_key)
|
@@ -109,7 +110,6 @@ module Aws
|
|
109
110
|
opts[:range_key] = rk if rk
|
110
111
|
h
|
111
112
|
end
|
112
|
-
mfi
|
113
113
|
end
|
114
114
|
|
115
115
|
def _si_key_schema(opts)
|
@@ -127,22 +127,20 @@ module Aws
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def _validate_required_lsi_keys(params)
|
130
|
-
|
131
|
-
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
132
|
-
else
|
130
|
+
unless params[:hash_key] && params[:range_key]
|
133
131
|
raise ArgumentError, 'Local Secondary Indexes require a hash and range key!'
|
134
132
|
end
|
133
|
+
|
134
|
+
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
135
135
|
end
|
136
136
|
|
137
137
|
def _validate_required_gsi_keys(params)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
_validate_attributes_exist(params[:hash_key])
|
143
|
-
end
|
138
|
+
raise ArgumentError, 'Global Secondary Indexes require at least a hash key!' unless params[:hash_key]
|
139
|
+
|
140
|
+
if params[:range_key]
|
141
|
+
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
144
142
|
else
|
145
|
-
|
143
|
+
_validate_attributes_exist(params[:hash_key])
|
146
144
|
end
|
147
145
|
end
|
148
146
|
|
@@ -150,12 +148,11 @@ module Aws
|
|
150
148
|
missing = attr_names.reject do |attr_name|
|
151
149
|
@attributes.present?(attr_name)
|
152
150
|
end
|
153
|
-
|
154
|
-
raise ArgumentError, "#{missing.join(', ')} not present in model attributes."\
|
155
|
-
' Please ensure that attributes are defined in the model'\
|
156
|
-
' class BEFORE defining an index on those attributes.'
|
151
|
+
return if missing.empty?
|
157
152
|
|
158
|
-
|
153
|
+
raise ArgumentError, "#{missing.join(', ')} not present in model attributes. " \
|
154
|
+
'Please ensure that attributes are defined in the model ' \
|
155
|
+
'class BEFORE defining an index on those attributes.'
|
159
156
|
end
|
160
157
|
end
|
161
158
|
end
|
@@ -194,11 +194,9 @@ module Aws
|
|
194
194
|
# @api private
|
195
195
|
def ttl_attribute(attribute_symbol)
|
196
196
|
attribute = @model_class.attributes.attribute_for(attribute_symbol)
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
raise ArgumentError, "Invalid attribute #{attribute_symbol} for #{@model_class}"
|
201
|
-
end
|
197
|
+
raise ArgumentError, "Invalid attribute #{attribute_symbol} for #{@model_class}" unless attribute
|
198
|
+
|
199
|
+
@ttl_attribute = attribute.database_name
|
202
200
|
end
|
203
201
|
|
204
202
|
# @api private
|
@@ -245,17 +243,18 @@ module Aws
|
|
245
243
|
# First up is TTL attribute. Since this migration is not exact match,
|
246
244
|
# we will only alter TTL status if we have a TTL attribute defined. We
|
247
245
|
# may someday support explicit TTL deletion, but we do not yet do this.
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
246
|
+
return unless @ttl_attribute
|
247
|
+
return if _ttl_compatibility_check
|
248
|
+
|
249
|
+
client.update_time_to_live(
|
250
|
+
table_name: @model_class.table_name,
|
251
|
+
time_to_live_specification: {
|
252
|
+
enabled: true,
|
253
|
+
attribute_name: @ttl_attribute
|
254
|
+
}
|
255
|
+
)
|
256
|
+
# Else TTL is compatible and we are done.
|
257
|
+
# Else our work is done.
|
259
258
|
end
|
260
259
|
|
261
260
|
# Checks the remote table for compatibility. Similar to +#exact_match?+,
|
@@ -382,7 +381,7 @@ module Aws
|
|
382
381
|
resp_gsis = resp.table.global_secondary_indexes
|
383
382
|
_add_global_secondary_index_throughput(opts, resp_gsis)
|
384
383
|
end
|
385
|
-
end
|
384
|
+
end
|
386
385
|
opts
|
387
386
|
elsif @billing_mode == 'PAY_PER_REQUEST'
|
388
387
|
{
|
@@ -400,9 +399,7 @@ module Aws
|
|
400
399
|
table_name: @model_class.table_name,
|
401
400
|
global_secondary_index_updates: gsi_updates
|
402
401
|
}
|
403
|
-
unless attribute_definitions.empty?
|
404
|
-
opts[:attribute_definitions] = attribute_definitions
|
405
|
-
end
|
402
|
+
opts[:attribute_definitions] = attribute_definitions unless attribute_definitions.empty?
|
406
403
|
opts
|
407
404
|
end
|
408
405
|
|
@@ -474,12 +471,12 @@ module Aws
|
|
474
471
|
exists = attribute_definitions.any? do |ad|
|
475
472
|
ad[:attribute_name] == attribute.database_name
|
476
473
|
end
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
474
|
+
next if exists
|
475
|
+
|
476
|
+
attribute_definitions << {
|
477
|
+
attribute_name: attribute.database_name,
|
478
|
+
attribute_type: attribute.dynamodb_type
|
479
|
+
}
|
483
480
|
end
|
484
481
|
end
|
485
482
|
attribute_definitions
|
@@ -566,15 +563,15 @@ module Aws
|
|
566
563
|
rpt[k] == v
|
567
564
|
end
|
568
565
|
elsif @billing_mode == 'PAY_PER_REQUEST'
|
569
|
-
pt_match = lpt.nil?
|
566
|
+
pt_match = lpt.nil?
|
570
567
|
else
|
571
568
|
raise ArgumentError, "Unsupported billing mode #{@billing_mode}"
|
572
569
|
end
|
573
570
|
|
574
571
|
rp = rgsi.projection.to_h
|
575
572
|
lp = lgsi[:projection]
|
576
|
-
rp[:non_key_attributes]
|
577
|
-
lp[:non_key_attributes]
|
573
|
+
rp[:non_key_attributes]&.sort!
|
574
|
+
lp[:non_key_attributes]&.sort!
|
578
575
|
p_match = rp == lp
|
579
576
|
|
580
577
|
ks_match && pt_match && p_match
|
@@ -584,15 +581,11 @@ module Aws
|
|
584
581
|
def _gsi_index_names(remote, local)
|
585
582
|
remote_index_names = Set.new
|
586
583
|
local_index_names = Set.new
|
587
|
-
|
588
|
-
|
589
|
-
remote_index_names.add(gsi.index_name)
|
590
|
-
end
|
584
|
+
remote&.each do |gsi|
|
585
|
+
remote_index_names.add(gsi.index_name)
|
591
586
|
end
|
592
|
-
|
593
|
-
|
594
|
-
local_index_names.add(gsi[:index_name].to_s)
|
595
|
-
end
|
587
|
+
local&.each do |gsi|
|
588
|
+
local_index_names.add(gsi[:index_name].to_s)
|
596
589
|
end
|
597
590
|
[remote_index_names, local_index_names]
|
598
591
|
end
|
@@ -601,17 +594,15 @@ module Aws
|
|
601
594
|
gsis = []
|
602
595
|
model_gsis = @model_class.global_secondary_indexes_for_migration
|
603
596
|
gsi_config = @global_secondary_indexes
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
end
|
614
|
-
end
|
597
|
+
model_gsis&.each do |mgsi|
|
598
|
+
config = gsi_config[mgsi[:index_name]]
|
599
|
+
gsis << if @billing_mode == 'PROVISIONED'
|
600
|
+
mgsi.merge(
|
601
|
+
provisioned_throughput: config.provisioned_throughput
|
602
|
+
)
|
603
|
+
else
|
604
|
+
mgsi
|
605
|
+
end
|
615
606
|
end
|
616
607
|
gsis
|
617
608
|
end
|
@@ -626,15 +617,13 @@ module Aws
|
|
626
617
|
if @billing_mode == 'PROVISIONED'
|
627
618
|
missing_config << 'read_capacity_units' unless @read_capacity_units
|
628
619
|
missing_config << 'write_capacity_units' unless @write_capacity_units
|
629
|
-
|
630
|
-
|
631
|
-
raise ArgumentError, "Cannot have billing mode #{@billing_mode} with provisioned capacity."
|
632
|
-
end
|
633
|
-
end
|
634
|
-
unless missing_config.empty?
|
635
|
-
msg = missing_config.join(', ')
|
636
|
-
raise Errors::MissingRequiredConfiguration, 'Missing: ' + msg
|
620
|
+
elsif @read_capacity_units || @write_capacity_units
|
621
|
+
raise ArgumentError, "Cannot have billing mode #{@billing_mode} with provisioned capacity."
|
637
622
|
end
|
623
|
+
return if missing_config.empty?
|
624
|
+
|
625
|
+
msg = missing_config.join(', ')
|
626
|
+
raise Errors::MissingRequiredConfiguration, "Missing: #{msg}"
|
638
627
|
end
|
639
628
|
|
640
629
|
# @api private
|
@@ -5,7 +5,7 @@ module Aws
|
|
5
5
|
class TableMigration
|
6
6
|
# @!attribute [rw] client
|
7
7
|
# @return [Aws::DynamoDB::Client] the
|
8
|
-
# {http://docs.aws.amazon.com/
|
8
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
9
9
|
# class used by this table migration instance.
|
10
10
|
attr_accessor :client
|
11
11
|
|
@@ -13,7 +13,7 @@ module Aws
|
|
13
13
|
# @param [Hash] opts
|
14
14
|
# @option opts [Aws::DynamoDB::Client] :client Allows you to inject your
|
15
15
|
# own
|
16
|
-
# {http://docs.aws.amazon.com/
|
16
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
17
17
|
# class. If this option is not included, a client will be constructed for
|
18
18
|
# you with default parameters.
|
19
19
|
def initialize(model, opts = {})
|
@@ -24,7 +24,7 @@ module Aws
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# This method calls
|
27
|
-
# {http://docs.aws.amazon.com/
|
27
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#create_table-instance_method
|
28
28
|
# Aws::DynamoDB::Client#create_table}, populating the attribute definitions and
|
29
29
|
# key schema based on your model class, as well as passing through other
|
30
30
|
# parameters as provided by you.
|
@@ -75,9 +75,9 @@ module Aws
|
|
75
75
|
end
|
76
76
|
if (gsis = @model.global_secondary_indexes_for_migration)
|
77
77
|
unless gsit || opts[:billing_mode] == 'PAY_PER_REQUEST'
|
78
|
-
raise ArgumentError, 'If you define global secondary indexes, you must also define'\
|
79
|
-
'
|
80
|
-
"
|
78
|
+
raise ArgumentError, 'If you define global secondary indexes, you must also define ' \
|
79
|
+
':global_secondary_index_throughput on table creation, ' \
|
80
|
+
"unless :billing_mode is set to 'PAY_PER_REQUEST'."
|
81
81
|
end
|
82
82
|
gsis_opts = if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
83
83
|
gsis
|
@@ -91,7 +91,7 @@ module Aws
|
|
91
91
|
end
|
92
92
|
|
93
93
|
# This method calls
|
94
|
-
# {http://docs.aws.amazon.com/
|
94
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#update_table-instance_method
|
95
95
|
# Aws::DynamoDB::Client#update_table} using the parameters that you provide.
|
96
96
|
#
|
97
97
|
# @param [Hash] opts options to pass on to the client call to
|
@@ -109,7 +109,7 @@ module Aws
|
|
109
109
|
end
|
110
110
|
|
111
111
|
# This method calls
|
112
|
-
# {http://docs.aws.amazon.com/
|
112
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#delete_table-instance_method
|
113
113
|
# Aws::DynamoDB::Client#delete_table} using the table name of your model.
|
114
114
|
#
|
115
115
|
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table did not
|
@@ -136,29 +136,25 @@ module Aws
|
|
136
136
|
end
|
137
137
|
|
138
138
|
def _assert_required_include(model)
|
139
|
-
|
140
|
-
|
141
|
-
|
139
|
+
return if model.include?(::Aws::Record)
|
140
|
+
|
141
|
+
raise Errors::InvalidModel, 'Table models must include Aws::Record'
|
142
142
|
end
|
143
143
|
|
144
144
|
def _validate_billing(opts)
|
145
145
|
valid_modes = %w[PAY_PER_REQUEST PROVISIONED]
|
146
|
-
if opts.key?(:billing_mode)
|
147
|
-
|
148
|
-
|
149
|
-
" current value is: #{opts[:billing_mode]}"
|
150
|
-
end
|
146
|
+
if opts.key?(:billing_mode) && !valid_modes.include?(opts[:billing_mode])
|
147
|
+
raise ArgumentError, ":billing_mode option must be one of #{valid_modes.join(', ')} " \
|
148
|
+
"current value is: #{opts[:billing_mode]}"
|
151
149
|
end
|
152
150
|
if opts.key?(:provisioned_throughput)
|
153
151
|
if opts[:billing_mode] == 'PAY_PER_REQUEST'
|
154
|
-
raise ArgumentError, 'when :provisioned_throughput option is specified, :billing_mode'\
|
155
|
-
"
|
156
|
-
end
|
157
|
-
else
|
158
|
-
if opts[:billing_mode] != 'PAY_PER_REQUEST'
|
159
|
-
raise ArgumentError, 'when :provisioned_throughput option is not specified,'\
|
160
|
-
" :billing_mode must be set to 'PAY_PER_REQUEST'"
|
152
|
+
raise ArgumentError, 'when :provisioned_throughput option is specified, :billing_mode ' \
|
153
|
+
"must either be unspecified or have a value of 'PROVISIONED'"
|
161
154
|
end
|
155
|
+
elsif opts[:billing_mode] != 'PAY_PER_REQUEST'
|
156
|
+
raise ArgumentError, 'when :provisioned_throughput option is not specified, ' \
|
157
|
+
":billing_mode must be set to 'PAY_PER_REQUEST'"
|
162
158
|
end
|
163
159
|
end
|
164
160
|
|
@@ -179,15 +175,15 @@ module Aws
|
|
179
175
|
exists = attr_def.find do |a|
|
180
176
|
a[:attribute_name] == key_schema[:attribute_name]
|
181
177
|
end
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
178
|
+
next if exists
|
179
|
+
|
180
|
+
attr = attributes.attribute_for(
|
181
|
+
attributes.db_to_attribute_name(key_schema[:attribute_name])
|
182
|
+
)
|
183
|
+
attr_def << {
|
184
|
+
attribute_name: attr.database_name,
|
185
|
+
attribute_type: attr.dynamodb_type
|
186
|
+
}
|
191
187
|
end
|
192
188
|
end
|
193
189
|
create_opts[:attribute_definitions] = attr_def
|
@@ -202,10 +198,10 @@ module Aws
|
|
202
198
|
params.merge(provisioned_throughput: throughput)
|
203
199
|
end
|
204
200
|
unless missing_throughput.empty?
|
205
|
-
raise ArgumentError, 'Missing provisioned throughput for the following global secondary'\
|
206
|
-
"
|
207
|
-
"
|
208
|
-
"
|
201
|
+
raise ArgumentError, 'Missing provisioned throughput for the following global secondary ' \
|
202
|
+
"indexes: #{missing_throughput.join(', ')}. GSIs: " \
|
203
|
+
"#{global_secondary_indexes} and defined throughput: " \
|
204
|
+
"#{gsi_throughput}"
|
209
205
|
end
|
210
206
|
ret
|
211
207
|
end
|
@@ -236,7 +236,7 @@ module Aws
|
|
236
236
|
elsif (check_record = item.delete(:check))
|
237
237
|
_transform_check_record(check_record, item)
|
238
238
|
else
|
239
|
-
raise ArgumentError, 'Invalid transact write item, must include an operation of '\
|
239
|
+
raise ArgumentError, 'Invalid transact write item, must include an operation of ' \
|
240
240
|
"type :save, :update, :delete, :update, or :check - #{item}"
|
241
241
|
|
242
242
|
end
|
@@ -250,13 +250,13 @@ module Aws
|
|
250
250
|
safety_expression = save_record.send(:prevent_overwrite_expression)
|
251
251
|
if opts.include?(:condition_expression)
|
252
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"\
|
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
260
|
"\tExtra Options: #{JSON.pretty_unparse(opts)}"
|
261
261
|
else
|
262
262
|
opts = opts.merge(safety_expression)
|
@@ -293,16 +293,16 @@ module Aws
|
|
293
293
|
opts[:key] = update_record.send(:key_values)
|
294
294
|
opts[:update_expression] = uex
|
295
295
|
# need to combine expression attribute names and values
|
296
|
-
if (names = opts[:expression_attribute_names])
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
if (values = opts[:expression_attribute_values])
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
296
|
+
opts[:expression_attribute_names] = if (names = opts[:expression_attribute_names])
|
297
|
+
exp_attr_names.merge(names)
|
298
|
+
else
|
299
|
+
exp_attr_names
|
300
|
+
end
|
301
|
+
opts[:expression_attribute_values] = if (values = opts[:expression_attribute_values])
|
302
|
+
exp_attr_values.merge(values)
|
303
|
+
else
|
304
|
+
exp_attr_values
|
305
|
+
end
|
306
306
|
{ update: opts }
|
307
307
|
end
|
308
308
|
|
data/lib/aws-record/record.rb
CHANGED
@@ -117,14 +117,13 @@ module Aws
|
|
117
117
|
# MyOtherTable.table_name # => "test_MyTable"
|
118
118
|
def table_name
|
119
119
|
# rubocop:disable Style/RedundantSelf
|
120
|
-
@table_name ||=
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
120
|
+
@table_name ||= if Aws::Record.extends_record?(self) &&
|
121
|
+
default_table_name(self.superclass) != self.superclass.table_name
|
122
|
+
self.superclass.instance_variable_get('@table_name')
|
123
|
+
else
|
124
|
+
default_table_name(self)
|
125
|
+
end
|
126
|
+
|
128
127
|
# rubocop:enable Style/RedundantSelf
|
129
128
|
end
|
130
129
|
|
@@ -247,6 +246,7 @@ module Aws
|
|
247
246
|
|
248
247
|
def default_table_name(klass)
|
249
248
|
return unless klass.name
|
249
|
+
|
250
250
|
klass.name.split('::').join('_')
|
251
251
|
end
|
252
252
|
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.
|
4
|
+
version: 2.12.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-
|
11
|
+
date: 2023-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-dynamodb
|
@@ -32,8 +32,7 @@ dependencies:
|
|
32
32
|
version: 1.85.0
|
33
33
|
description: Provides an object mapping abstraction for Amazon DynamoDB.
|
34
34
|
email:
|
35
|
-
-
|
36
|
-
- alexwoo@amazon.com
|
35
|
+
- aws-dr-rubygems@amazon.com
|
37
36
|
executables: []
|
38
37
|
extensions: []
|
39
38
|
extra_rdoc_files: []
|
@@ -87,7 +86,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
86
|
requirements:
|
88
87
|
- - ">="
|
89
88
|
- !ruby/object:Gem::Version
|
90
|
-
version: '
|
89
|
+
version: '2.3'
|
91
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
91
|
requirements:
|
93
92
|
- - ">="
|