-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Expand file tree
/
Copy pathscaffold.rb
More file actions
150 lines (141 loc) · 5.42 KB
/
scaffold.rb
File metadata and controls
150 lines (141 loc) · 5.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
# Purpose
#
# Shows how to use the AWS SDK for Ruby with Amazon DynamoDB to
# create, populate, and delete a table that stores data about movies.
#
# 1. Create a new DynamoDB table
# 2. Load the table with data from a JSON file.
# 3. Delete table
# snippet-start:[ruby.example_code.dynamodb.helper.DynamoDBBasics]
require 'aws-sdk-dynamodb'
require 'json'
require 'open-uri'
require 'zip'
# snippet-start:[ruby.example_code.dynamodb.Scaffold]
# Encapsulates an Amazon DynamoDB table of movie data.
class Scaffold
attr_reader :dynamo_resource, :table_name, :table
def initialize(table_name)
client = Aws::DynamoDB::Client.new(region: 'us-east-1')
@dynamo_resource = Aws::DynamoDB::Resource.new(client: client)
@table_name = table_name
@table = nil
@logger = Logger.new($stdout)
@logger.level = Logger::DEBUG
end
# snippet-end:[ruby.example_code.dynamodb.Scaffold]
# snippet-start:[ruby.example_code.dynamodb.DescribeTable]
# Determines whether a table exists. As a side effect, stores the table in
# a member variable.
#
# @param table_name [String] The name of the table to check.
# @return [Boolean] True when the table exists; otherwise, False.
def exists?(table_name)
@dynamo_resource.client.describe_table(table_name: table_name)
@logger.debug("Table #{table_name} exists")
rescue Aws::DynamoDB::Errors::ResourceNotFoundException
@logger.debug("Table #{table_name} doesn't exist")
false
rescue Aws::DynamoDB::Errors::ServiceError => e
puts("Couldn't check for existence of #{table_name}:\n")
puts("\t#{e.code}: #{e.message}")
raise
end
# snippet-end:[ruby.example_code.dynamodb.DescribeTable]
# snippet-start:[ruby.example_code.dynamodb.CreateTable]
# Creates an Amazon DynamoDB table that can be used to store movie data.
# The table uses the release year of the movie as the partition key and the
# title as the sort key.
#
# @param table_name [String] The name of the table to create.
# @return [Aws::DynamoDB::Table] The newly created table.
def create_table(table_name)
@table = @dynamo_resource.create_table(
table_name: table_name,
key_schema: [
{ attribute_name: 'year', key_type: 'HASH' }, # Partition key
{ attribute_name: 'title', key_type: 'RANGE' } # Sort key
],
attribute_definitions: [
{ attribute_name: 'year', attribute_type: 'N' },
{ attribute_name: 'title', attribute_type: 'S' }
],
billing_mode: 'PAY_PER_REQUEST'
)
@dynamo_resource.client.wait_until(:table_exists, table_name: table_name)
@table
rescue Aws::DynamoDB::Errors::ServiceError => e
@logger.error("Failed create table #{table_name}:\n#{e.code}: #{e.message}")
raise
end
# snippet-end:[ruby.example_code.dynamodb.CreateTable]
# snippet-start:[ruby.example_code.dynamodb.BatchWriteItem]
# Fills an Amazon DynamoDB table with the specified data. Items are sent in
# batches of 25 until all items are written.
#
# @param movies [Enumerable] The data to put in the table. Each item must contain at least
# the keys required by the schema that was specified when the
# table was created.
def write_batch(movies)
index = 0
slice_size = 25
while index < movies.length
movie_items = []
movies[index, slice_size].each do |movie|
movie_items.append({ put_request: { item: movie } })
end
@dynamo_resource.client.batch_write_item({ request_items: { @table.name => movie_items } })
index += slice_size
end
rescue Aws::DynamoDB::Errors::ServiceError => e
puts(
"Couldn't load data into table #{@table.name}. Here's why:"
)
puts("\t#{e.code}: #{e.message}")
raise
end
# snippet-end:[ruby.example_code.dynamodb.BatchWriteItem]
# snippet-start:[ruby.example_code.dynamodb.DeleteTable]
# Deletes the table.
def delete_table
@table.delete
@table = nil
rescue Aws::DynamoDB::Errors::ServiceError => e
puts("Couldn't delete table. Here's why:")
puts("\t#{e.code}: #{e.message}")
raise
end
# snippet-end:[ruby.example_code.dynamodb.DeleteTable]
# snippet-start:[ruby.example_code.dynamodb.helper.get_sample_movie_data]
# Gets sample movie data, either from a local file or by first downloading it from
# the Amazon DynamoDB Developer Guide.
#
# @param movie_file_name [String] The local file name where the movie data is stored in JSON format.
# @return [Hash] The movie data as a Hash.
def fetch_movie_data(movie_file_name)
if !File.file?(movie_file_name)
@logger.debug("Downloading #{movie_file_name}...")
movie_content = URI.open(
'https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/moviedata.zip'
)
movie_json = ''
Zip::File.open_buffer(movie_content) do |zip|
zip.each do |entry|
movie_json = entry.get_input_stream.read
end
end
else
movie_json = File.read(movie_file_name)
end
movie_data = JSON.parse(movie_json)
# The sample file lists over 4000 movies. This returns only the first 250.
movie_data.slice(0, 250)
rescue StandardError => e
puts("Failure downloading movie data:\n#{e}")
raise
end
# snippet-end:[ruby.example_code.dynamodb.helper.get_sample_movie_data]
end
# snippet-end:[ruby.example_code.dynamodb.helper.DynamoDBBasics]