aws-record 1.0.0.pre.1 → 1.0.0.pre.2
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/lib/aws-record.rb +22 -6
- data/lib/aws-record/record.rb +107 -4
- data/lib/aws-record/record/attribute.rb +50 -1
- data/lib/aws-record/record/attributes.rb +56 -38
- data/lib/aws-record/record/attributes/boolean_marshaler.rb +13 -0
- data/lib/aws-record/record/attributes/date_marshaler.rb +13 -0
- data/lib/aws-record/record/attributes/date_time_marshaler.rb +13 -0
- data/lib/aws-record/record/attributes/float_marshaler.rb +13 -0
- data/lib/aws-record/record/attributes/integer_marshaler.rb +13 -0
- data/lib/aws-record/record/attributes/string_marshaler.rb +13 -0
- data/lib/aws-record/record/errors.rb +13 -0
- data/lib/aws-record/record/item_collection.rb +42 -0
- data/lib/aws-record/record/item_operations.rb +40 -8
- data/lib/aws-record/record/query.rb +56 -0
- data/lib/aws-record/record/secondary_indexes.rb +156 -0
- data/lib/aws-record/record/table_migration.rb +116 -2
- data/lib/aws-record/record/version.rb +14 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f411d61078b7eeb8fbd7081d51c3f41b1c9116ca
|
4
|
+
data.tar.gz: 073b4953897897aba7298b5ba90e8050a015fcde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba35bcbfadff82862f5170c428d213c23157307c07ef9325263d877596cb2c32e0a9b65ee150e7492538b67f422c90d3f8112b5d51def09508e55c974ae6944f
|
7
|
+
data.tar.gz: 9301a70e55fae642dd83c814720ab78543dae3ec12e1c806df096326009308dce7fbb2666a1a8610cd18c69418be9e70d93649b1d2780b42523fb9361c7e04a6
|
data/lib/aws-record.rb
CHANGED
@@ -1,15 +1,31 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
require 'aws-sdk-resources'
|
2
15
|
|
3
16
|
module Aws
|
4
17
|
autoload :Record, 'aws-record/record'
|
5
18
|
|
6
19
|
module Record
|
7
|
-
autoload :Attribute,
|
8
|
-
autoload :Attributes,
|
9
|
-
autoload :Errors,
|
10
|
-
autoload :
|
11
|
-
autoload :
|
12
|
-
autoload :
|
20
|
+
autoload :Attribute, 'aws-record/record/attribute'
|
21
|
+
autoload :Attributes, 'aws-record/record/attributes'
|
22
|
+
autoload :Errors, 'aws-record/record/errors'
|
23
|
+
autoload :ItemCollection, 'aws-record/record/item_collection'
|
24
|
+
autoload :ItemOperations, 'aws-record/record/item_operations'
|
25
|
+
autoload :Query, 'aws-record/record/query'
|
26
|
+
autoload :SecondaryIndexes, 'aws-record/record/secondary_indexes'
|
27
|
+
autoload :TableMigration, 'aws-record/record/table_migration'
|
28
|
+
autoload :VERSION, 'aws-record/record/version'
|
13
29
|
|
14
30
|
module Attributes
|
15
31
|
autoload :StringMarshaler, 'aws-record/record/attributes/string_marshaler'
|
data/lib/aws-record/record.rb
CHANGED
@@ -1,9 +1,33 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
16
|
+
|
17
|
+
# Usage of {Aws::Record} requires only that you include this module. This
|
18
|
+
# method will then pull in the other default modules.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# class MyTable
|
22
|
+
# include Aws::Record
|
23
|
+
# # Attribute definitions go here...
|
24
|
+
# end
|
3
25
|
def self.included(sub_class)
|
4
|
-
sub_class.extend
|
5
|
-
sub_class.include
|
6
|
-
sub_class.include
|
26
|
+
sub_class.send(:extend, RecordClassMethods)
|
27
|
+
sub_class.send(:include, Attributes)
|
28
|
+
sub_class.send(:include, ItemOperations)
|
29
|
+
sub_class.send(:include, Query)
|
30
|
+
sub_class.send(:include, SecondaryIndexes)
|
7
31
|
end
|
8
32
|
|
9
33
|
private
|
@@ -12,6 +36,25 @@ module Aws
|
|
12
36
|
end
|
13
37
|
|
14
38
|
module RecordClassMethods
|
39
|
+
|
40
|
+
# Returns the Amazon DynamoDB table name for this model class.
|
41
|
+
#
|
42
|
+
# By default, this will simply be the name of the class. However, you can
|
43
|
+
# also define a custom table name at the class level to be anything that
|
44
|
+
# you want.
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# class MyTable
|
48
|
+
# include Aws::Record
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# class MyTableTest
|
52
|
+
# include Aws::Record
|
53
|
+
# set_table_name "test_MyTable"
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# MyTable.table_name # => "MyTable"
|
57
|
+
# MyOtherTable.table_name # => "test_MyTable"
|
15
58
|
def table_name
|
16
59
|
if @table_name
|
17
60
|
@table_name
|
@@ -20,10 +63,33 @@ module Aws
|
|
20
63
|
end
|
21
64
|
end
|
22
65
|
|
66
|
+
# Allows you to set a custom Amazon DynamoDB table name for this model
|
67
|
+
# class.
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# class MyTable
|
71
|
+
# include Aws::Record
|
72
|
+
# set_table_name "prod_MyTable"
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# class MyTableTest
|
76
|
+
# include Aws::Record
|
77
|
+
# set_table_name "test_MyTable"
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
# MyTable.table_name # => "prod_MyTable"
|
81
|
+
# MyOtherTable.table_name # => "test_MyTable"
|
23
82
|
def set_table_name(name)
|
24
83
|
@table_name = name
|
25
84
|
end
|
26
85
|
|
86
|
+
# Fetches the table's provisioned throughput from the associated Amazon
|
87
|
+
# DynamoDB table.
|
88
|
+
#
|
89
|
+
# @return [Hash] a hash containing the +:read_capacity_units+ and
|
90
|
+
# +:write_capacity_units+ of your remote table.
|
91
|
+
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table name does
|
92
|
+
# not exist in DynamoDB.
|
27
93
|
def provisioned_throughput
|
28
94
|
begin
|
29
95
|
resp = dynamodb_client.describe_table(table_name: @table_name)
|
@@ -37,6 +103,9 @@ module Aws
|
|
37
103
|
end
|
38
104
|
end
|
39
105
|
|
106
|
+
# Checks if the model's table name exists in Amazon DynamoDB.
|
107
|
+
#
|
108
|
+
# @return [Boolean] true if the table does exist, false if it does not.
|
40
109
|
def table_exists?
|
41
110
|
begin
|
42
111
|
resp = dynamodb_client.describe_table(table_name: @table_name)
|
@@ -50,16 +119,50 @@ module Aws
|
|
50
119
|
end
|
51
120
|
end
|
52
121
|
|
122
|
+
# Configures the Amazon DynamoDB client used by this class and all
|
123
|
+
# instances of this class.
|
124
|
+
#
|
125
|
+
# Please note that this method is also called internally when you first
|
126
|
+
# attempt to perform an operation against the remote end, if you have not
|
127
|
+
# already configured a client. As such, please read and understand the
|
128
|
+
# documentation in the AWS SDK for Ruby V2 around
|
129
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/index.html#Configuration configuration}
|
130
|
+
# to ensure you understand how default configuration behavior works. When
|
131
|
+
# in doubt, call this method to ensure your client is configured the way
|
132
|
+
# you want it to be configured.
|
133
|
+
#
|
134
|
+
# @param [Hash] opts the options you wish to use to create the client.
|
135
|
+
# Note that if you include the option +:client+, all other options
|
136
|
+
# will be ignored. See the documentation for other options in the
|
137
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#initialize-instance_method AWS SDK for Ruby V2}.
|
138
|
+
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in your
|
139
|
+
# own pre-configured client.
|
53
140
|
def configure_client(opts = {})
|
54
141
|
provided_client = opts.delete(:client)
|
55
|
-
opts[:user_agent_suffix] =
|
142
|
+
opts[:user_agent_suffix] = _user_agent(opts.delete(:user_agent_suffix))
|
56
143
|
client = provided_client || Aws::DynamoDB::Client.new(opts)
|
57
144
|
@dynamodb_client = client
|
58
145
|
end
|
59
146
|
|
147
|
+
# Gets the
|
148
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
149
|
+
# instance that this model uses. When called for the first time, if
|
150
|
+
# {#configure_client} has not yet been called, will configure a new client
|
151
|
+
# for you with default parameters.
|
152
|
+
#
|
153
|
+
# @return [Aws::DynamoDB::Client] the Amazon DynamoDB client instance.
|
60
154
|
def dynamodb_client
|
61
155
|
@dynamodb_client ||= configure_client
|
62
156
|
end
|
157
|
+
|
158
|
+
private
|
159
|
+
def _user_agent(custom)
|
160
|
+
if custom
|
161
|
+
custom
|
162
|
+
else
|
163
|
+
" aws-record/#{VERSION}"
|
164
|
+
end
|
165
|
+
end
|
63
166
|
end
|
64
167
|
end
|
65
168
|
end
|
@@ -1,9 +1,40 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
class Attribute
|
4
17
|
|
5
18
|
attr_reader :name, :database_name, :dynamodb_type
|
6
19
|
|
20
|
+
# @param [Symbol] name Name of the attribute. It should be a name that is
|
21
|
+
# safe to use as a method.
|
22
|
+
# @param [Hash] options
|
23
|
+
# @option options [Marshaler] :marshaler The marshaler for this attribute.
|
24
|
+
# So long as you provide a marshaler which implements `#type_cast` and
|
25
|
+
# `#serialize` that consume raw values as expected, you can bring your
|
26
|
+
# own marshaler type.
|
27
|
+
# @option options [Array] :validators An array of validator classes that
|
28
|
+
# will be run when an attribute is checked for validity.
|
29
|
+
# @option options [String] :database_attribute_name Optional attribute
|
30
|
+
# used to specify a different name for database persistence than the
|
31
|
+
# `name` parameter. Must be unique (you can't have overlap between
|
32
|
+
# database attribute names and the names of other attributes).
|
33
|
+
# @option options [String] :dynamodb_type Generally used for keys and
|
34
|
+
# index attributes, one of "S", "N", "B", "BOOL", "SS", "NS", "BS",
|
35
|
+
# "M", "L". Optional if this attribute will never be used for a key or
|
36
|
+
# secondary index, but most convenience methods for setting attributes
|
37
|
+
# will provide this.
|
7
38
|
def initialize(name, options = {})
|
8
39
|
@name = name
|
9
40
|
@database_name = options[:database_attribute_name] || name.to_s
|
@@ -12,14 +43,31 @@ module Aws
|
|
12
43
|
@validators = options[:validators] || []
|
13
44
|
end
|
14
45
|
|
46
|
+
# Attempts to type cast a raw value into the attribute's type. This call
|
47
|
+
# will forward the raw value to this attribute's marshaler class.
|
48
|
+
#
|
49
|
+
# @return [Object] the type cast object. Return type is dependent on the
|
50
|
+
# marshaler used. See your attribute's marshaler class for details.
|
15
51
|
def type_cast(raw_value)
|
16
52
|
@marshaler.type_cast(raw_value)
|
17
53
|
end
|
18
54
|
|
55
|
+
# Attempts to serialize a raw value into the attribute's serialized
|
56
|
+
# storage type. This call will forward the raw value to this attribute's
|
57
|
+
# marshaler class.
|
58
|
+
#
|
59
|
+
# @return [Object] the serialized object. Return type is dependent on the
|
60
|
+
# marshaler used. See your attribute's marshaler class for details.
|
19
61
|
def serialize(raw_value)
|
20
62
|
@marshaler.serialize(raw_value)
|
21
63
|
end
|
22
64
|
|
65
|
+
# Checks if the raw value is valid for this attribute. This is done by
|
66
|
+
# type casting the raw value, then running that value through each
|
67
|
+
# validator present for this attribute.
|
68
|
+
#
|
69
|
+
# @return [Boolean] true if the raw value is valid for this attribute,
|
70
|
+
# false if it is not.
|
23
71
|
def valid?(raw_value)
|
24
72
|
value = type_cast(raw_value)
|
25
73
|
@validators.all? do |validator|
|
@@ -27,8 +75,9 @@ module Aws
|
|
27
75
|
end
|
28
76
|
end
|
29
77
|
|
78
|
+
# @api private
|
30
79
|
def extract(dynamodb_item)
|
31
|
-
dynamodb_item[database_name]
|
80
|
+
dynamodb_item[@database_name]
|
32
81
|
end
|
33
82
|
|
34
83
|
end
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Attributes
|
@@ -30,21 +43,21 @@ module Aws
|
|
30
43
|
# as you provide a marshaler which implements `#type_cast` and
|
31
44
|
# `#serialize` that consume raw values as expected, you can bring your
|
32
45
|
# own marshaler type. Convenience methods will provide this for you.
|
33
|
-
# @param [Hash]
|
34
|
-
# @option
|
46
|
+
# @param [Hash] opts
|
47
|
+
# @option opts [Array] :validators An array of validator classes that
|
35
48
|
# will be run when an attribute is checked for validity.
|
36
|
-
# @option
|
49
|
+
# @option opts [String] :database_attribute_name Optional attribute
|
37
50
|
# used to specify a different name for database persistence than the
|
38
51
|
# `name` parameter. Must be unique (you can't have overlap between
|
39
52
|
# database attribute names and the names of other attributes).
|
40
|
-
# @option
|
53
|
+
# @option opts [String] :dynamodb_type Generally used for keys and
|
41
54
|
# index attributes, one of "S", "N", "B", "BOOL", "SS", "NS", "BS",
|
42
55
|
# "M", "L". Optional if this attribute will never be used for a key or
|
43
56
|
# secondary index, but most convenience methods for setting attributes
|
44
57
|
# will provide this.
|
45
|
-
# @option
|
58
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
46
59
|
# the hash key for the table.
|
47
|
-
# @option
|
60
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
48
61
|
# the range key for the table.
|
49
62
|
def attr(name, marshaler, opts = {})
|
50
63
|
validate_attr_name(name)
|
@@ -68,84 +81,84 @@ module Aws
|
|
68
81
|
#
|
69
82
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
70
83
|
# is safe to use as a method.
|
71
|
-
# @param [Hash]
|
72
|
-
# @option
|
84
|
+
# @param [Hash] opts
|
85
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
73
86
|
# the hash key for the table.
|
74
|
-
# @option
|
87
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
75
88
|
# the range key for the table.
|
76
|
-
def string_attr(
|
89
|
+
def string_attr(name, opts = {})
|
77
90
|
opts[:dynamodb_type] = "S"
|
78
|
-
attr(
|
91
|
+
attr(name, Attributes::StringMarshaler, opts)
|
79
92
|
end
|
80
93
|
|
81
94
|
# Define a boolean-type attribute for your model.
|
82
95
|
#
|
83
96
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
84
97
|
# is safe to use as a method.
|
85
|
-
# @param [Hash]
|
86
|
-
# @option
|
98
|
+
# @param [Hash] opts
|
99
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
87
100
|
# the hash key for the table.
|
88
|
-
# @option
|
101
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
89
102
|
# the range key for the table.
|
90
|
-
def boolean_attr(
|
103
|
+
def boolean_attr(name, opts = {})
|
91
104
|
opts[:dynamodb_type] = "BOOL"
|
92
|
-
attr(
|
105
|
+
attr(name, Attributes::BooleanMarshaler, opts)
|
93
106
|
end
|
94
107
|
|
95
108
|
# Define a integer-type attribute for your model.
|
96
109
|
#
|
97
110
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
98
111
|
# is safe to use as a method.
|
99
|
-
# @param [Hash]
|
100
|
-
# @option
|
112
|
+
# @param [Hash] opts
|
113
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
101
114
|
# the hash key for the table.
|
102
|
-
# @option
|
115
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
103
116
|
# the range key for the table.
|
104
|
-
def integer_attr(
|
117
|
+
def integer_attr(name, opts = {})
|
105
118
|
opts[:dynamodb_type] = "N"
|
106
|
-
attr(
|
119
|
+
attr(name, Attributes::IntegerMarshaler, opts)
|
107
120
|
end
|
108
121
|
|
109
122
|
# Define a float-type attribute for your model.
|
110
123
|
#
|
111
124
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
112
125
|
# is safe to use as a method.
|
113
|
-
# @param [Hash]
|
114
|
-
# @option
|
126
|
+
# @param [Hash] opts
|
127
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
115
128
|
# the hash key for the table.
|
116
|
-
# @option
|
129
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
117
130
|
# the range key for the table.
|
118
|
-
def float_attr(
|
131
|
+
def float_attr(name, opts = {})
|
119
132
|
opts[:dynamodb_type] = "N"
|
120
|
-
attr(
|
133
|
+
attr(name, Attributes::FloatMarshaler, opts)
|
121
134
|
end
|
122
135
|
|
123
136
|
# Define a date-type attribute for your model.
|
124
137
|
#
|
125
138
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
126
139
|
# is safe to use as a method.
|
127
|
-
# @param [Hash]
|
128
|
-
# @option
|
140
|
+
# @param [Hash] opts
|
141
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
129
142
|
# the hash key for the table.
|
130
|
-
# @option
|
143
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
131
144
|
# the range key for the table.
|
132
|
-
def date_attr(
|
145
|
+
def date_attr(name, opts = {})
|
133
146
|
opts[:dynamodb_type] = "S"
|
134
|
-
attr(
|
147
|
+
attr(name, Attributes::DateMarshaler, opts)
|
135
148
|
end
|
136
149
|
|
137
150
|
# Define a datetime-type attribute for your model.
|
138
151
|
#
|
139
152
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
140
153
|
# is safe to use as a method.
|
141
|
-
# @param [Hash]
|
142
|
-
# @option
|
154
|
+
# @param [Hash] opts
|
155
|
+
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
143
156
|
# the hash key for the table.
|
144
|
-
# @option
|
157
|
+
# @option opts [Boolean] :range_key Set to true if this attribute is
|
145
158
|
# the range key for the table.
|
146
|
-
def datetime_attr(
|
159
|
+
def datetime_attr(name, opts = {})
|
147
160
|
opts[:dynamodb_type] = "S"
|
148
|
-
attr(
|
161
|
+
attr(name, Attributes::DateTimeMarshaler, opts)
|
149
162
|
end
|
150
163
|
|
151
164
|
# @return [Hash] hash of symbolized attribute names to attribute objects
|
@@ -153,6 +166,11 @@ module Aws
|
|
153
166
|
@attributes
|
154
167
|
end
|
155
168
|
|
169
|
+
# @return [Hash] hash of database names to attribute names
|
170
|
+
def storage_attributes
|
171
|
+
@storage_attributes
|
172
|
+
end
|
173
|
+
|
156
174
|
# @return [Aws::Record::Attribute,nil]
|
157
175
|
def hash_key
|
158
176
|
@attributes[@keys[:hash]]
|
@@ -218,12 +236,12 @@ module Aws
|
|
218
236
|
end
|
219
237
|
|
220
238
|
def check_for_naming_collisions(name, storage_name)
|
221
|
-
if @attributes[storage_name]
|
239
|
+
if @attributes[storage_name.to_sym]
|
222
240
|
raise Errors::NameCollision.new(
|
223
241
|
"Custom storage name #{storage_name} already exists as an"\
|
224
242
|
" attribute name in #{@attributes}"
|
225
243
|
)
|
226
|
-
elsif @storage_attributes[name]
|
244
|
+
elsif @storage_attributes[name.to_s]
|
227
245
|
raise Errors::NameCollision.new(
|
228
246
|
"Attribute name #{name} already exists as a custom storage"\
|
229
247
|
" name in #{@storage_attributes}"
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Attributes
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
require 'date'
|
2
15
|
|
3
16
|
module Aws
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
require 'date'
|
2
15
|
|
3
16
|
module Aws
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Attributes
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Attributes
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Attributes
|
@@ -1,3 +1,16 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module Errors
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Aws
|
2
|
+
module Record
|
3
|
+
class ItemCollection
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(search_method, search_params, model, client)
|
7
|
+
@search_method = search_method
|
8
|
+
@search_params = search_params
|
9
|
+
@model = model
|
10
|
+
@client = client
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
return enum_for(:each) unless block_given?
|
15
|
+
unless @result
|
16
|
+
@result = @client.send(@search_method, @search_params)
|
17
|
+
end
|
18
|
+
@result.each_page do |page|
|
19
|
+
items = _build_items_from_response(page.items, @model)
|
20
|
+
items.each do |item|
|
21
|
+
yield item
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def _build_items_from_response(items, model)
|
28
|
+
ret = []
|
29
|
+
items.each do |item|
|
30
|
+
record = model.new
|
31
|
+
data = record.instance_variable_get("@data")
|
32
|
+
model.attributes.each do |name, attr|
|
33
|
+
data[name] = attr.extract(item)
|
34
|
+
end
|
35
|
+
ret << record
|
36
|
+
end
|
37
|
+
ret
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,11 +1,32 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
module ItemOperations
|
4
17
|
|
18
|
+
# @api private
|
5
19
|
def self.included(sub_class)
|
6
20
|
sub_class.extend(ItemOperationsClassMethods)
|
7
21
|
end
|
8
22
|
|
23
|
+
# Saves this instance of an item to Amazon DynamoDB using the
|
24
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method Aws::DynamoDB::Client#put_item}
|
25
|
+
# API. Uses this item instance's attributes in order to build the request
|
26
|
+
# on your behalf.
|
27
|
+
#
|
28
|
+
# @raise [Aws::Record::Errors::KeyMissing] if a required key attribute
|
29
|
+
# does not have a value within this item instance.
|
9
30
|
def save
|
10
31
|
dynamodb_client.put_item(
|
11
32
|
table_name: self.class.table_name,
|
@@ -13,6 +34,10 @@ module Aws
|
|
13
34
|
)
|
14
35
|
end
|
15
36
|
|
37
|
+
# Deletes the item instance that matches the key values of this item
|
38
|
+
# instance in Amazon DynamoDB. Uses the
|
39
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_item-instance_method Aws::DynamoDB::Client#delete_item}
|
40
|
+
# API.
|
16
41
|
def delete!
|
17
42
|
dynamodb_client.delete_item(
|
18
43
|
table_name: self.class.table_name,
|
@@ -60,6 +85,21 @@ module Aws
|
|
60
85
|
end
|
61
86
|
|
62
87
|
module ItemOperationsClassMethods
|
88
|
+
|
89
|
+
# @example Usage Example
|
90
|
+
# class MyModel
|
91
|
+
# include Aws::Record
|
92
|
+
# integer_attr :id, hash_key: true
|
93
|
+
# string_attr :name, range_key: true
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# MyModel.find(id: 1, name: "First")
|
97
|
+
#
|
98
|
+
# @param [Hash] opts attribute-value pairs for the key you wish to
|
99
|
+
# search for.
|
100
|
+
# @return [Aws::Record] builds and returns an instance of your model.
|
101
|
+
# @raise [Aws::Record::Errors::KeyMissing] if your option parameters do
|
102
|
+
# not include all table keys.
|
63
103
|
def find(opts)
|
64
104
|
key = {}
|
65
105
|
@keys.each_value do |attr_sym|
|
@@ -92,14 +132,6 @@ module Aws
|
|
92
132
|
end
|
93
133
|
record
|
94
134
|
end
|
95
|
-
|
96
|
-
def user_agent(custom)
|
97
|
-
if custom
|
98
|
-
custom
|
99
|
-
else
|
100
|
-
" aws-record/#{VERSION}"
|
101
|
-
end
|
102
|
-
end
|
103
135
|
end
|
104
136
|
|
105
137
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
14
|
+
module Aws
|
15
|
+
module Record
|
16
|
+
module Query
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
def self.included(sub_class)
|
20
|
+
sub_class.extend(QueryClassMethods)
|
21
|
+
end
|
22
|
+
|
23
|
+
module QueryClassMethods
|
24
|
+
|
25
|
+
# This method calls
|
26
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method Aws::DynamoDB::Client#query},
|
27
|
+
# populating the +:table_name+ parameter from the model class, and
|
28
|
+
# combining this with the other parameters you provide.
|
29
|
+
#
|
30
|
+
# @param [Hash] opts options to pass on to the client call to +#query+.
|
31
|
+
# See the documentation above in the AWS SDK for Ruby V2.
|
32
|
+
# @return [Aws::Record::ItemCollection] an enumerable collection of the
|
33
|
+
# query result.
|
34
|
+
def query(opts)
|
35
|
+
query_opts = opts.merge(table_name: table_name)
|
36
|
+
ItemCollection.new(:query, query_opts, self, dynamodb_client)
|
37
|
+
end
|
38
|
+
|
39
|
+
# This method calls
|
40
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#scan-instance_method Aws::DynamoDB::Client#scan},
|
41
|
+
# populating the +:table_name+ parameter from the model class, and
|
42
|
+
# combining this with the other parameters you provide.
|
43
|
+
#
|
44
|
+
# @param [Hash] opts options to pass on to the client call to +#scan+.
|
45
|
+
# See the documentation above in the AWS SDK for Ruby V2.
|
46
|
+
# @return [Aws::Record::ItemCollection] an enumerable collection of the
|
47
|
+
# scan result.
|
48
|
+
def scan(opts = {})
|
49
|
+
scan_opts = opts.merge(table_name: table_name)
|
50
|
+
ItemCollection.new(:scan, scan_opts, self, dynamodb_client)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
14
|
+
module Aws
|
15
|
+
module Record
|
16
|
+
module SecondaryIndexes
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
def self.included(sub_class)
|
20
|
+
sub_class.instance_variable_set("@local_secondary_indexes", {})
|
21
|
+
sub_class.instance_variable_set("@global_secondary_indexes", {})
|
22
|
+
sub_class.extend(SecondaryIndexesClassMethods)
|
23
|
+
end
|
24
|
+
|
25
|
+
module SecondaryIndexesClassMethods
|
26
|
+
|
27
|
+
# Creates a local secondary index for the model. Learn more about Local
|
28
|
+
# Secondary Indexes in the
|
29
|
+
# {http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html Amazon DynamoDB Developer Guide}.
|
30
|
+
#
|
31
|
+
# @param [Symbol] name index name for this local secondary index
|
32
|
+
# @param [Hash] opts
|
33
|
+
# @option opts [Symbol] :range_key the range key used by this local
|
34
|
+
# secondary index. Note that the hash key MUST be the table's hash
|
35
|
+
# key, and so that value will be filled in for you.
|
36
|
+
# @option opts [Hash] :projection a hash which defines which attributes
|
37
|
+
# are copied from the table to the index. See shape details in the
|
38
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Types/Projection.html AWS SDK for Ruby V2 docs}.
|
39
|
+
def local_secondary_index(name, opts)
|
40
|
+
opts[:hash_key] = hash_key.name
|
41
|
+
_validate_required_lsi_keys(opts)
|
42
|
+
local_secondary_indexes[name] = opts
|
43
|
+
end
|
44
|
+
|
45
|
+
# Creates a global secondary index for the model. Learn more about
|
46
|
+
# Global Secondary Indexes in the
|
47
|
+
# {http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html Amazon DynamoDB Developer Guide}.
|
48
|
+
#
|
49
|
+
# @param [Symbol] name index name for this global secondary index
|
50
|
+
# @param [Hash] opts
|
51
|
+
# @option opts [Symbol] :hash_key the hash key used by this global
|
52
|
+
# secondary index.
|
53
|
+
# @option opts [Symbol] :range_key the range key used by this global
|
54
|
+
# secondary index.
|
55
|
+
# @option opts [Hash] :projection a hash which defines which attributes
|
56
|
+
# are copied from the table to the index. See shape details in the
|
57
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Types/Projection.html AWS SDK for Ruby V2 docs}.
|
58
|
+
def global_secondary_index(name, opts)
|
59
|
+
_validate_required_gsi_keys(opts)
|
60
|
+
global_secondary_indexes[name] = opts
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Hash] hash of local secondary index names to the index's
|
64
|
+
# attributes.
|
65
|
+
def local_secondary_indexes
|
66
|
+
@local_secondary_indexes
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return [Hash] hash of global secondary index names to the index's
|
70
|
+
# attributes.
|
71
|
+
def global_secondary_indexes
|
72
|
+
@global_secondary_indexes
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Hash] hash of the local secondary indexes in a form suitable
|
76
|
+
# for use in a table migration. For example, any attributes which
|
77
|
+
# have a unique database storage name will use that name instead.
|
78
|
+
def local_secondary_indexes_for_migration
|
79
|
+
_migration_format_indexes(local_secondary_indexes)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [Hash] hash of the global secondary indexes in a form suitable
|
83
|
+
# for use in a table migration. For example, any attributes which
|
84
|
+
# have a unique database storage name will use that name instead.
|
85
|
+
def global_secondary_indexes_for_migration
|
86
|
+
_migration_format_indexes(global_secondary_indexes)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def _migration_format_indexes(indexes)
|
91
|
+
return nil if indexes.empty?
|
92
|
+
indexes.collect do |name, opts|
|
93
|
+
h = { index_name: name }
|
94
|
+
h[:key_schema] = _si_key_schema(opts)
|
95
|
+
opts.delete(:hash_key)
|
96
|
+
opts.delete(:range_key)
|
97
|
+
h = h.merge(opts)
|
98
|
+
h
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _si_key_schema(opts)
|
103
|
+
key_schema = [{
|
104
|
+
key_type: "HASH",
|
105
|
+
attribute_name: @attributes[opts[:hash_key]].database_name
|
106
|
+
}]
|
107
|
+
if opts[:range_key]
|
108
|
+
key_schema << {
|
109
|
+
key_type: "RANGE",
|
110
|
+
attribute_name: @attributes[opts[:range_key]].database_name
|
111
|
+
}
|
112
|
+
end
|
113
|
+
key_schema
|
114
|
+
end
|
115
|
+
|
116
|
+
def _validate_required_lsi_keys(params)
|
117
|
+
if params[:hash_key] && params[:range_key]
|
118
|
+
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
119
|
+
else
|
120
|
+
raise ArgumentError.new(
|
121
|
+
"Local Secondary Indexes require a hash and range key!"
|
122
|
+
)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def _validate_required_gsi_keys(params)
|
127
|
+
if params[:hash_key]
|
128
|
+
if params[:range_key]
|
129
|
+
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
130
|
+
else
|
131
|
+
_validate_attributes_exist(params[:hash_key])
|
132
|
+
end
|
133
|
+
else
|
134
|
+
raise ArgumentError.new(
|
135
|
+
"Global Secondary Indexes require at least a hash key!"
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def _validate_attributes_exist(*attr_names)
|
141
|
+
missing = attr_names.select do |attr_name|
|
142
|
+
@attributes[attr_name].nil?
|
143
|
+
end
|
144
|
+
unless missing.empty?
|
145
|
+
raise ArgumentError.new(
|
146
|
+
"#{missing.join(", ")} not present in model attributes."\
|
147
|
+
" Please ensure that attributes are defined in the model"\
|
148
|
+
" class BEFORE defining a index on those attributes."
|
149
|
+
)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -1,24 +1,88 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
16
|
class TableMigration
|
4
17
|
|
18
|
+
# @!attribute [rw] client
|
19
|
+
# @return [Aws::DynamoDB::Client] the
|
20
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
21
|
+
# class used by this table migration instance.
|
5
22
|
attr_accessor :client
|
6
23
|
|
7
|
-
|
24
|
+
# @param [Aws::Record] model a model class that includes {Aws::Record}.
|
25
|
+
# @param [Hash] opts
|
26
|
+
# @option opts [Aws::DynamoDB::Client] :client Allows you to inject your
|
27
|
+
# own
|
28
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html Aws::DynamoDB::Client}
|
29
|
+
# class. If this option is not included, a client will be constructed for
|
30
|
+
# you with default parameters.
|
31
|
+
def initialize(model, opts = {})
|
8
32
|
assert_model_valid(model)
|
9
33
|
@model = model
|
10
|
-
@client = client || Aws::DynamoDB::Client.new
|
34
|
+
@client = opts[:client] || Aws::DynamoDB::Client.new
|
11
35
|
end
|
12
36
|
|
37
|
+
# This method calls
|
38
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#create_table-instance_method Aws::DynamoDB::Client#create_table},
|
39
|
+
# populating the attribute definitions and key schema based on your model
|
40
|
+
# class, as well as passing through other parameters as provided by you.
|
41
|
+
#
|
42
|
+
# @param [Hash] opts options to pass on to the client call to
|
43
|
+
# +#create_table+. See the documentation above in the AWS SDK for Ruby
|
44
|
+
# V2.
|
45
|
+
# @option opts [Hash] :provisioned_throughput This is a required argument,
|
46
|
+
# in which you must specify the +:read_capacity_units+ and
|
47
|
+
# +:write_capacity_units+ of your new table.
|
48
|
+
# @option opts [Hash] :global_secondary_index_throughput This argument is
|
49
|
+
# required if you define any global secondary indexes. It should map your
|
50
|
+
# global secondary index names to their provisioned throughput, similar
|
51
|
+
# to how you define the provisioned throughput for the table in general.
|
13
52
|
def create!(opts)
|
53
|
+
gsit = opts.delete(:global_secondary_index_throughput)
|
14
54
|
create_opts = opts.merge({
|
15
55
|
table_name: @model.table_name,
|
16
56
|
attribute_definitions: attribute_definitions,
|
17
57
|
key_schema: key_schema
|
18
58
|
})
|
59
|
+
if lsis = @model.local_secondary_indexes_for_migration
|
60
|
+
create_opts[:local_secondary_indexes] = lsis
|
61
|
+
_append_to_attribute_definitions(lsis, create_opts)
|
62
|
+
end
|
63
|
+
if gsis = @model.global_secondary_indexes_for_migration
|
64
|
+
unless gsit
|
65
|
+
raise ArgumentError.new(
|
66
|
+
"If you define global secondary indexes, you must also define"\
|
67
|
+
" :global_secondary_index_throughput on table creation."
|
68
|
+
)
|
69
|
+
end
|
70
|
+
gsis_with_throughput = _add_throughout_to_gsis(gsis, gsit)
|
71
|
+
create_opts[:global_secondary_indexes] = gsis_with_throughput
|
72
|
+
_append_to_attribute_definitions(gsis, create_opts)
|
73
|
+
end
|
19
74
|
@client.create_table(create_opts)
|
20
75
|
end
|
21
76
|
|
77
|
+
# This method calls
|
78
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_table-instance_method Aws::DynamoDB::Client#update_table}
|
79
|
+
# using the parameters that you provide.
|
80
|
+
#
|
81
|
+
# @param [Hash] opts options to pass on to the client call to
|
82
|
+
# +#update_table+. See the documentation above in the AWS SDK for Ruby
|
83
|
+
# V2.
|
84
|
+
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table does not
|
85
|
+
# currently exist in Amazon DynamoDB.
|
22
86
|
def update!(opts)
|
23
87
|
begin
|
24
88
|
update_opts = opts.merge({
|
@@ -30,6 +94,12 @@ module Aws
|
|
30
94
|
end
|
31
95
|
end
|
32
96
|
|
97
|
+
# This method calls
|
98
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#delete_table-instance_method Aws::DynamoDB::Client#delete_table}
|
99
|
+
# using the table name of your model.
|
100
|
+
#
|
101
|
+
# @raise [Aws::Record::Errors::TableDoesNotExist] if the table did not
|
102
|
+
# exist in Amazon DynamoDB at the time of calling.
|
33
103
|
def delete!
|
34
104
|
begin
|
35
105
|
@client.delete_table(table_name: @model.table_name)
|
@@ -38,6 +108,10 @@ module Aws
|
|
38
108
|
end
|
39
109
|
end
|
40
110
|
|
111
|
+
# This method waits on the table specified in the model to exist and be
|
112
|
+
# marked as ACTIVE in Amazon DynamoDB. Note that this method can run for
|
113
|
+
# several minutes if the table does not exist, and is not created within
|
114
|
+
# the wait period.
|
41
115
|
def wait_until_available
|
42
116
|
@client.wait_until(:table_exists, table_name: @model.table_name)
|
43
117
|
end
|
@@ -69,6 +143,46 @@ module Aws
|
|
69
143
|
end
|
70
144
|
end
|
71
145
|
|
146
|
+
def _append_to_attribute_definitions(secondary_indexes, create_opts)
|
147
|
+
attr_def = create_opts[:attribute_definitions]
|
148
|
+
secondary_indexes.each do |si|
|
149
|
+
si[:key_schema].each do |key_schema|
|
150
|
+
exists = attr_def.find { |a|
|
151
|
+
a[:attribute_name] == key_schema[:attribute_name]
|
152
|
+
}
|
153
|
+
unless exists
|
154
|
+
attr = @model.attributes[
|
155
|
+
@model.storage_attributes[key_schema[:attribute_name]]
|
156
|
+
]
|
157
|
+
attr_def << {
|
158
|
+
attribute_name: attr.database_name,
|
159
|
+
attribute_type: attr.dynamodb_type
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
create_opts[:attribute_definitions] = attr_def
|
165
|
+
end
|
166
|
+
|
167
|
+
def _add_throughout_to_gsis(global_secondary_indexes, gsi_throughput)
|
168
|
+
missing_throughput = []
|
169
|
+
ret = global_secondary_indexes.map do |params|
|
170
|
+
name = params[:index_name]
|
171
|
+
throughput = gsi_throughput[name]
|
172
|
+
missing_throughput << name unless throughput
|
173
|
+
params.merge(provisioned_throughput: throughput)
|
174
|
+
end
|
175
|
+
unless missing_throughput.empty?
|
176
|
+
raise ArgumentError.new(
|
177
|
+
"Missing provisioned throughput for the following global secondary"\
|
178
|
+
" indexes: #{missing_throughput.join(", ")}. GSIs:"\
|
179
|
+
" #{global_secondary_indexes} and defined throughput:"\
|
180
|
+
" #{gsi_throughput}"
|
181
|
+
)
|
182
|
+
end
|
183
|
+
ret
|
184
|
+
end
|
185
|
+
|
72
186
|
def key_schema
|
73
187
|
keys.map do |type, attr|
|
74
188
|
{
|
@@ -1,5 +1,18 @@
|
|
1
|
+
# Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
4
|
+
# use this file except in compliance with the License. A copy of the License is
|
5
|
+
# located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is distributed on
|
10
|
+
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
11
|
+
# or implied. See the License for the specific language governing permissions
|
12
|
+
# and limitations under the License.
|
13
|
+
|
1
14
|
module Aws
|
2
15
|
module Record
|
3
|
-
VERSION = "1.0.0.pre.
|
16
|
+
VERSION = "1.0.0.pre.2"
|
4
17
|
end
|
5
18
|
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: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.2
|
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:
|
11
|
+
date: 2016-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-resources
|
@@ -42,7 +42,10 @@ files:
|
|
42
42
|
- lib/aws-record/record/attributes/integer_marshaler.rb
|
43
43
|
- lib/aws-record/record/attributes/string_marshaler.rb
|
44
44
|
- lib/aws-record/record/errors.rb
|
45
|
+
- lib/aws-record/record/item_collection.rb
|
45
46
|
- lib/aws-record/record/item_operations.rb
|
47
|
+
- lib/aws-record/record/query.rb
|
48
|
+
- lib/aws-record/record/secondary_indexes.rb
|
46
49
|
- lib/aws-record/record/table_migration.rb
|
47
50
|
- lib/aws-record/record/version.rb
|
48
51
|
homepage: http://github.com/aws/aws-sdk-ruby-record
|
@@ -65,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
68
|
version: 1.3.1
|
66
69
|
requirements: []
|
67
70
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
71
|
+
rubygems_version: 2.4.8
|
69
72
|
signing_key:
|
70
73
|
specification_version: 4
|
71
74
|
summary: AWS Record library for Amazon DynamoDB
|