dynamoid 1.1.0 → 1.2.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 +4 -4
- data/.document +5 -0
- data/.gitignore +67 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/CHANGELOG.md +20 -2
- data/Gemfile +3 -1
- data/{README.markdown → README.md} +30 -6
- data/Rakefile +17 -20
- data/dynamoid.gemspec +45 -68
- data/lib/dynamoid.rb +20 -18
- data/lib/dynamoid/adapter.rb +11 -2
- data/lib/dynamoid/adapter_plugin/aws_sdk_v2.rb +313 -48
- data/lib/dynamoid/associations/association.rb +11 -0
- data/lib/dynamoid/associations/many_association.rb +4 -2
- data/lib/dynamoid/associations/single_association.rb +1 -1
- data/lib/dynamoid/components.rb +1 -0
- data/lib/dynamoid/config.rb +3 -0
- data/lib/dynamoid/criteria/chain.rb +12 -10
- data/lib/dynamoid/document.rb +5 -3
- data/lib/dynamoid/errors.rb +17 -3
- data/lib/dynamoid/fields.rb +19 -5
- data/lib/dynamoid/finders.rb +65 -0
- data/lib/dynamoid/indexes.rb +273 -0
- data/lib/dynamoid/persistence.rb +14 -3
- data/lib/dynamoid/validations.rb +27 -0
- data/lib/dynamoid/version.rb +3 -0
- metadata +41 -15
data/lib/dynamoid/adapter.rb
CHANGED
@@ -17,7 +17,7 @@ module Dynamoid
|
|
17
17
|
|
18
18
|
def tables
|
19
19
|
if !@tables_.value
|
20
|
-
@tables_.swap{|value, args| benchmark('Cache Tables') {list_tables}}
|
20
|
+
@tables_.swap{|value, args| benchmark('Cache Tables') { list_tables } }
|
21
21
|
end
|
22
22
|
@tables_.value
|
23
23
|
end
|
@@ -131,7 +131,16 @@ module Dynamoid
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
|
134
|
+
# @since 0.2.0
|
135
|
+
def delete_table(table_name, *args)
|
136
|
+
if tables.include?(table_name)
|
137
|
+
benchmark('Delete Table') { adapter.delete_table(table_name, *args) }
|
138
|
+
idx = tables.index(table_name)
|
139
|
+
tables.delete_at(idx)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
[:batch_get_item, :delete_item, :get_item, :list_tables, :put_item, :truncate].each do |m|
|
135
144
|
# Method delegation with benchmark to the underlying adapter. Faster than relying on method_missing.
|
136
145
|
#
|
137
146
|
# @since 0.2.0
|
@@ -3,6 +3,33 @@ module Dynamoid
|
|
3
3
|
|
4
4
|
# The AwsSdkV2 adapter provides support for the aws-sdk version 2 for ruby.
|
5
5
|
class AwsSdkV2
|
6
|
+
EQ = "EQ".freeze
|
7
|
+
RANGE_MAP = {
|
8
|
+
range_greater_than: 'GT',
|
9
|
+
range_less_than: 'LT',
|
10
|
+
range_gte: 'GE',
|
11
|
+
range_lte: 'LE',
|
12
|
+
range_begins_with: 'BEGINS_WITH',
|
13
|
+
range_between: 'BETWEEN',
|
14
|
+
range_eq: 'EQ'
|
15
|
+
}
|
16
|
+
HASH_KEY = "HASH".freeze
|
17
|
+
RANGE_KEY = "RANGE".freeze
|
18
|
+
STRING_TYPE = "S".freeze
|
19
|
+
NUM_TYPE = "N".freeze
|
20
|
+
BINARY_TYPE = "B".freeze
|
21
|
+
TABLE_STATUSES = {
|
22
|
+
creating: "CREATING",
|
23
|
+
updating: "UPDATING",
|
24
|
+
deleting: "DELETING",
|
25
|
+
active: "ACTIVE"
|
26
|
+
}.freeze
|
27
|
+
PARSE_TABLE_STATUS = ->(resp, lookup = :table) {
|
28
|
+
# lookup is table for describe_table API
|
29
|
+
# lookup is table_description for create_table API
|
30
|
+
# because Amazon, damnit.
|
31
|
+
resp.send(lookup).table_status
|
32
|
+
}
|
6
33
|
attr_reader :table_cache
|
7
34
|
|
8
35
|
# Establish the connection to DynamoDB.
|
@@ -100,41 +127,91 @@ module Dynamoid
|
|
100
127
|
# @param [String] table_name the name of the table to create
|
101
128
|
# @param [Symbol] key the table's primary key (defaults to :id)
|
102
129
|
# @param [Hash] options provide a range key here if the table has a composite key
|
103
|
-
#
|
130
|
+
# @option options [Array<Dynamoid::Indexes::Index>] local_secondary_indexes
|
131
|
+
# @option options [Array<Dynamoid::Indexes::Index>] global_secondary_indexes
|
132
|
+
# @option options [Symbol] hash_key_type The type of the hash key
|
133
|
+
# @option options [Boolean] sync Wait for table status to be ACTIVE?
|
104
134
|
# @since 1.0.0
|
105
135
|
def create_table(table_name, key = :id, options = {})
|
106
136
|
Dynamoid.logger.info "Creating #{table_name} table. This could take a while."
|
107
137
|
read_capacity = options[:read_capacity] || Dynamoid::Config.read_capacity
|
108
138
|
write_capacity = options[:write_capacity] || Dynamoid::Config.write_capacity
|
109
|
-
range_key = options[:range_key]
|
110
139
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
attribute_definitions
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
140
|
+
secondary_indexes = options.slice(
|
141
|
+
:local_secondary_indexes,
|
142
|
+
:global_secondary_indexes
|
143
|
+
)
|
144
|
+
ls_indexes = options[:local_secondary_indexes]
|
145
|
+
gs_indexes = options[:global_secondary_indexes]
|
146
|
+
|
147
|
+
key_schema = {
|
148
|
+
:hash_key_schema => { key => (options[:hash_key_type] || :string) },
|
149
|
+
:range_key_schema => options[:range_key]
|
150
|
+
}
|
151
|
+
attribute_definitions = build_all_attribute_definitions(
|
152
|
+
key_schema,
|
153
|
+
secondary_indexes
|
154
|
+
)
|
155
|
+
key_schema = aws_key_schema(
|
156
|
+
key_schema[:hash_key_schema],
|
157
|
+
key_schema[:range_key_schema]
|
158
|
+
)
|
159
|
+
|
160
|
+
client_opts = {
|
161
|
+
table_name: table_name,
|
127
162
|
provisioned_throughput: {
|
128
163
|
read_capacity_units: read_capacity,
|
129
164
|
write_capacity_units: write_capacity
|
130
165
|
},
|
131
166
|
key_schema: key_schema,
|
132
167
|
attribute_definitions: attribute_definitions
|
133
|
-
|
168
|
+
}
|
169
|
+
|
170
|
+
if ls_indexes.present?
|
171
|
+
client_opts[:local_secondary_indexes] = ls_indexes.map do |index|
|
172
|
+
index_to_aws_hash(index)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if gs_indexes.present?
|
177
|
+
client_opts[:global_secondary_indexes] = gs_indexes.map do |index|
|
178
|
+
index_to_aws_hash(index)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
resp = client.create_table(client_opts)
|
182
|
+
options[:sync] = true if !options.has_key?(:sync) && ls_indexes.present? || gs_indexes.present?
|
183
|
+
until_past_table_status(table_name) if options[:sync] &&
|
184
|
+
(status = PARSE_TABLE_STATUS.call(resp, :table_description)) &&
|
185
|
+
status != TABLE_STATUSES[:creating]
|
186
|
+
# Response to original create_table, which, if options[:sync]
|
187
|
+
# may have an outdated table_description.table_status of "CREATING"
|
188
|
+
resp
|
134
189
|
rescue Aws::DynamoDB::Errors::ResourceInUseException => e
|
135
190
|
Dynamoid.logger.error "Table #{table_name} cannot be created as it already exists"
|
136
191
|
end
|
137
192
|
|
193
|
+
# Create a table on DynamoDB *synchronously*.
|
194
|
+
# This usually takes a long time to complete.
|
195
|
+
# CreateTable is normally an asynchronous operation.
|
196
|
+
# You can optionally define secondary indexes on the new table,
|
197
|
+
# as part of the CreateTable operation.
|
198
|
+
# If you want to create multiple tables with secondary indexes on them,
|
199
|
+
# you must create the tables sequentially.
|
200
|
+
# Only one table with secondary indexes can be
|
201
|
+
# in the CREATING state at any given time.
|
202
|
+
# See: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method
|
203
|
+
#
|
204
|
+
# @param [String] table_name the name of the table to create
|
205
|
+
# @param [Symbol] key the table's primary key (defaults to :id)
|
206
|
+
# @param [Hash] options provide a range key here if the table has a composite key
|
207
|
+
# @option options [Array<Dynamoid::Indexes::Index>] local_secondary_indexes
|
208
|
+
# @option options [Array<Dynamoid::Indexes::Index>] global_secondary_indexes
|
209
|
+
# @option options [Symbol] hash_key_type The type of the hash key
|
210
|
+
# @since 1.2.0
|
211
|
+
def create_table_synchronously(table_name, key = :id, options = {})
|
212
|
+
create_table(table_name, key, options.merge(sync: true))
|
213
|
+
end
|
214
|
+
|
138
215
|
# Removes an item from DynamoDB.
|
139
216
|
#
|
140
217
|
# @param [String] table_name the name of the table
|
@@ -160,11 +237,22 @@ module Dynamoid
|
|
160
237
|
# Deletes an entire table from DynamoDB.
|
161
238
|
#
|
162
239
|
# @param [String] table_name the name of the table to destroy
|
240
|
+
# @option options [Boolean] sync Wait for table status check to raise ResourceNotFoundException
|
163
241
|
#
|
164
242
|
# @since 1.0.0
|
165
|
-
def delete_table(table_name)
|
166
|
-
client.delete_table(table_name: table_name)
|
167
|
-
|
243
|
+
def delete_table(table_name, options = {})
|
244
|
+
resp = client.delete_table(table_name: table_name)
|
245
|
+
until_past_table_status(table_name, :deleting) if options[:sync] &&
|
246
|
+
(status = PARSE_TABLE_STATUS.call(resp, :table_description)) &&
|
247
|
+
status != TABLE_STATUSES[:deleting]
|
248
|
+
table_cache.delete(table_name)
|
249
|
+
rescue Aws::DynamoDB::Errors::ResourceInUseException => e
|
250
|
+
Dynamoid.logger.error "Table #{table_name} cannot be deleted as it is in use"
|
251
|
+
raise e
|
252
|
+
end
|
253
|
+
|
254
|
+
def delete_table_synchronously(table_name, options = {})
|
255
|
+
delete_table(table_name, options.merge(sync: true))
|
168
256
|
end
|
169
257
|
|
170
258
|
# @todo Add a DescribeTable method.
|
@@ -275,14 +363,21 @@ module Dynamoid
|
|
275
363
|
# @todo Provide support for various other options http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method
|
276
364
|
def query(table_name, opts = {})
|
277
365
|
table = describe_table(table_name)
|
278
|
-
hk = table.hash_key.to_s
|
279
|
-
rng = table.range_key.to_s
|
280
|
-
q = opts.slice(
|
366
|
+
hk = (opts[:hash_key].present? ? opts[:hash_key] : table.hash_key).to_s
|
367
|
+
rng = (opts[:range_key].present? ? opts[:range_key] : table.range_key).to_s
|
368
|
+
q = opts.slice(
|
369
|
+
:consistent_read,
|
370
|
+
:scan_index_forward,
|
371
|
+
:limit,
|
372
|
+
:select,
|
373
|
+
:index_name
|
374
|
+
)
|
281
375
|
|
282
376
|
opts.delete(:consistent_read)
|
283
377
|
opts.delete(:scan_index_forward)
|
284
378
|
opts.delete(:limit)
|
285
379
|
opts.delete(:select)
|
380
|
+
opts.delete(:index_name)
|
286
381
|
|
287
382
|
opts.delete(:next_token).tap do |token|
|
288
383
|
break unless token
|
@@ -325,17 +420,6 @@ module Dynamoid
|
|
325
420
|
}
|
326
421
|
end
|
327
422
|
|
328
|
-
EQ = "EQ".freeze
|
329
|
-
|
330
|
-
RANGE_MAP = {
|
331
|
-
range_greater_than: 'GT',
|
332
|
-
range_less_than: 'LT',
|
333
|
-
range_gte: 'GE',
|
334
|
-
range_lte: 'LE',
|
335
|
-
range_begins_with: 'BEGINS_WITH',
|
336
|
-
range_between: 'BETWEEN'
|
337
|
-
}
|
338
|
-
|
339
423
|
# Scan the DynamoDB table. This is usually a very slow operation as it naively filters all data on
|
340
424
|
# the DynamoDB servers.
|
341
425
|
#
|
@@ -378,7 +462,6 @@ module Dynamoid
|
|
378
462
|
end
|
379
463
|
end
|
380
464
|
|
381
|
-
|
382
465
|
#
|
383
466
|
# Truncates all records in the given table
|
384
467
|
#
|
@@ -391,7 +474,8 @@ module Dynamoid
|
|
391
474
|
rk = table.range_key
|
392
475
|
|
393
476
|
scan(table_name, {}, {}).each do |attributes|
|
394
|
-
opts = {
|
477
|
+
opts = {}
|
478
|
+
opts[:range_key] = attributes[rk.to_sym] if rk
|
395
479
|
delete_item(table_name, attributes[hk], opts)
|
396
480
|
end
|
397
481
|
end
|
@@ -402,18 +486,55 @@ module Dynamoid
|
|
402
486
|
|
403
487
|
protected
|
404
488
|
|
405
|
-
|
406
|
-
|
407
|
-
|
489
|
+
def check_table_status?(counter, resp, expect_status)
|
490
|
+
status = PARSE_TABLE_STATUS.call(resp)
|
491
|
+
again = counter < Dynamoid::Config.sync_retry_max_times &&
|
492
|
+
status == TABLE_STATUSES[expect_status]
|
493
|
+
{again: again, status: status, counter: counter}
|
494
|
+
end
|
495
|
+
|
496
|
+
def until_past_table_status(table_name, status = :creating)
|
497
|
+
counter = 0
|
498
|
+
resp = nil
|
499
|
+
begin
|
500
|
+
check = {again: true}
|
501
|
+
while check[:again]
|
502
|
+
sleep Dynamoid::Config.sync_retry_wait_seconds
|
503
|
+
resp = client.describe_table({ table_name: table_name })
|
504
|
+
check = check_table_status?(counter, resp, status)
|
505
|
+
Dynamoid.logger.info "Checked table status for #{table_name} (check #{check.inspect})"
|
506
|
+
counter += 1
|
507
|
+
end
|
508
|
+
# If you issue a DescribeTable request immediately after a CreateTable
|
509
|
+
# request, DynamoDB might return a ResourceNotFoundException.
|
510
|
+
# This is because DescribeTable uses an eventually consistent query,
|
511
|
+
# and the metadata for your table might not be available at that moment.
|
512
|
+
# Wait for a few seconds, and then try the DescribeTable request again.
|
513
|
+
# See: http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#describe_table-instance_method
|
514
|
+
rescue Aws::DynamoDB::Errors::ResourceNotFoundException => e
|
515
|
+
case status
|
516
|
+
when :creating then
|
517
|
+
if counter >= Dynamoid::Config.sync_retry_max_times
|
518
|
+
Dynamoid.logger.warn "Waiting on table metadata for #{table_name} (check #{counter})"
|
519
|
+
retry # start over at first line of begin, does not reset counter
|
520
|
+
else
|
521
|
+
Dynamoid.logger.error "Exhausted max retries (Dynamoid::Config.sync_retry_max_times) waiting on table metadata for #{table_name} (check #{counter})"
|
522
|
+
raise e
|
523
|
+
end
|
524
|
+
else
|
525
|
+
# When deleting a table, "not found" is the goal.
|
526
|
+
Dynamoid.logger.info "Checked table status for #{table_name}: Not Found (check #{check.inspect})"
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
408
530
|
|
409
531
|
#Converts from symbol to the API string for the given data type
|
410
532
|
# E.g. :number -> 'N'
|
411
533
|
def api_type(type)
|
412
534
|
case(type)
|
413
|
-
when :string
|
414
|
-
when :number
|
415
|
-
when :
|
416
|
-
when :boolean then BOOLEAN_TYPE
|
535
|
+
when :string then STRING_TYPE
|
536
|
+
when :number then NUM_TYPE
|
537
|
+
when :binary then BINARY_TYPE
|
417
538
|
else raise "Unknown type: #{type}"
|
418
539
|
end
|
419
540
|
end
|
@@ -445,9 +566,6 @@ module Dynamoid
|
|
445
566
|
expected
|
446
567
|
end
|
447
568
|
|
448
|
-
HASH_KEY = "HASH".freeze
|
449
|
-
RANGE_KEY = "RANGE".freeze
|
450
|
-
|
451
569
|
#
|
452
570
|
# New, semi-arbitrary API to get data on the table
|
453
571
|
#
|
@@ -466,6 +584,153 @@ module Dynamoid
|
|
466
584
|
end
|
467
585
|
end
|
468
586
|
|
587
|
+
# Converts a Dynamoid::Indexes::Index to an AWS API-compatible hash.
|
588
|
+
# This resulting hash is of the form:
|
589
|
+
#
|
590
|
+
# {
|
591
|
+
# index_name: String
|
592
|
+
# keys: {
|
593
|
+
# hash_key: aws_key_schema (hash)
|
594
|
+
# range_key: aws_key_schema (hash)
|
595
|
+
# }
|
596
|
+
# projection: {
|
597
|
+
# projection_type: (ALL, KEYS_ONLY, INCLUDE) String
|
598
|
+
# non_key_attributes: (optional) Array
|
599
|
+
# }
|
600
|
+
# provisioned_throughput: {
|
601
|
+
# read_capacity_units: Integer
|
602
|
+
# write_capacity_units: Integer
|
603
|
+
# }
|
604
|
+
# }
|
605
|
+
#
|
606
|
+
# @param [Dynamoid::Indexes::Index] index the index.
|
607
|
+
# @return [Hash] hash representing an AWS Index definition.
|
608
|
+
def index_to_aws_hash(index)
|
609
|
+
key_schema = aws_key_schema(index.hash_key_schema, index.range_key_schema)
|
610
|
+
|
611
|
+
hash = {
|
612
|
+
:index_name => index.name,
|
613
|
+
:key_schema => key_schema,
|
614
|
+
:projection => {
|
615
|
+
:projection_type => index.projection_type.to_s.upcase
|
616
|
+
}
|
617
|
+
}
|
618
|
+
|
619
|
+
# If the projection type is include, specify the non key attributes
|
620
|
+
if index.projection_type == :include
|
621
|
+
hash[:projection][:non_key_attributes] = index.projected_attributes
|
622
|
+
end
|
623
|
+
|
624
|
+
# Only global secondary indexes have a separate throughput.
|
625
|
+
if index.type == :global_secondary
|
626
|
+
hash[:provisioned_throughput] = {
|
627
|
+
:read_capacity_units => index.read_capacity,
|
628
|
+
:write_capacity_units => index.write_capacity
|
629
|
+
}
|
630
|
+
end
|
631
|
+
hash
|
632
|
+
end
|
633
|
+
|
634
|
+
# Converts hash_key_schema and range_key_schema to aws_key_schema
|
635
|
+
# @param [Hash] hash_key_schema eg: {:id => :string}
|
636
|
+
# @param [Hash] range_key_schema eg: {:created_at => :number}
|
637
|
+
# @return [Array]
|
638
|
+
def aws_key_schema(hash_key_schema, range_key_schema)
|
639
|
+
schema = [{
|
640
|
+
attribute_name: hash_key_schema.keys.first.to_s,
|
641
|
+
key_type: HASH_KEY
|
642
|
+
}]
|
643
|
+
|
644
|
+
if range_key_schema.present?
|
645
|
+
schema << {
|
646
|
+
attribute_name: range_key_schema.keys.first.to_s,
|
647
|
+
key_type: RANGE_KEY
|
648
|
+
}
|
649
|
+
end
|
650
|
+
schema
|
651
|
+
end
|
652
|
+
|
653
|
+
# Builds aws attributes definitions based off of primary hash/range and
|
654
|
+
# secondary indexes
|
655
|
+
#
|
656
|
+
# @param key_data
|
657
|
+
# @option key_data [Hash] hash_key_schema - eg: {:id => :string}
|
658
|
+
# @option key_data [Hash] range_key_schema - eg: {:created_at => :number}
|
659
|
+
# @param [Hash] secondary_indexes
|
660
|
+
# @option secondary_indexes [Array<Dynamoid::Indexes::Index>] :local_secondary_indexes
|
661
|
+
# @option secondary_indexes [Array<Dynamoid::Indexes::Index>] :global_secondary_indexes
|
662
|
+
def build_all_attribute_definitions(key_schema, secondary_indexes = {})
|
663
|
+
ls_indexes = secondary_indexes[:local_secondary_indexes]
|
664
|
+
gs_indexes = secondary_indexes[:global_secondary_indexes]
|
665
|
+
|
666
|
+
attribute_definitions = []
|
667
|
+
|
668
|
+
attribute_definitions << build_attribute_definitions(
|
669
|
+
key_schema[:hash_key_schema],
|
670
|
+
key_schema[:range_key_schema]
|
671
|
+
)
|
672
|
+
|
673
|
+
if ls_indexes.present?
|
674
|
+
ls_indexes.map do |index|
|
675
|
+
attribute_definitions << build_attribute_definitions(
|
676
|
+
index.hash_key_schema,
|
677
|
+
index.range_key_schema
|
678
|
+
)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
if gs_indexes.present?
|
683
|
+
gs_indexes.map do |index|
|
684
|
+
attribute_definitions << build_attribute_definitions(
|
685
|
+
index.hash_key_schema,
|
686
|
+
index.range_key_schema
|
687
|
+
)
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
attribute_definitions.flatten!
|
692
|
+
# uniq these definitions because range keys might be common between
|
693
|
+
# primary and secondary indexes
|
694
|
+
attribute_definitions.uniq!
|
695
|
+
attribute_definitions
|
696
|
+
end
|
697
|
+
|
698
|
+
|
699
|
+
# Builds an attribute definitions based on hash key and range key
|
700
|
+
# @params [Hash] hash_key_schema - eg: {:id => :string}
|
701
|
+
# @params [Hash] range_key_schema - eg: {:created_at => :datetime}
|
702
|
+
# @return [Array]
|
703
|
+
def build_attribute_definitions(hash_key_schema, range_key_schema = nil)
|
704
|
+
attrs = []
|
705
|
+
|
706
|
+
attrs << attribute_definition_element(
|
707
|
+
hash_key_schema.keys.first,
|
708
|
+
hash_key_schema.values.first
|
709
|
+
)
|
710
|
+
|
711
|
+
if range_key_schema.present?
|
712
|
+
attrs << attribute_definition_element(
|
713
|
+
range_key_schema.keys.first,
|
714
|
+
range_key_schema.values.first
|
715
|
+
)
|
716
|
+
end
|
717
|
+
|
718
|
+
attrs
|
719
|
+
end
|
720
|
+
|
721
|
+
# Builds an aws attribute definition based on name and dynamoid type
|
722
|
+
# @params [Symbol] name - eg: :id
|
723
|
+
# @params [Symbol] dynamoid_type - eg: :string
|
724
|
+
# @return [Hash]
|
725
|
+
def attribute_definition_element(name, dynamoid_type)
|
726
|
+
aws_type = api_type(dynamoid_type)
|
727
|
+
|
728
|
+
{
|
729
|
+
:attribute_name => name.to_s,
|
730
|
+
:attribute_type => aws_type
|
731
|
+
}
|
732
|
+
end
|
733
|
+
|
469
734
|
#
|
470
735
|
# Represents a table. Exposes data from the "DescribeTable" API call, and also
|
471
736
|
# provides methods for coercing values to the proper types based on the table's schema data
|