aws-record 2.10.1 → 2.11.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/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/lib/aws-record/record/attribute.rb +4 -6
- data/lib/aws-record/record/attributes.rb +36 -49
- data/lib/aws-record/record/batch.rb +13 -12
- data/lib/aws-record/record/batch_read.rb +5 -2
- data/lib/aws-record/record/buildable_search.rb +29 -26
- data/lib/aws-record/record/client_configuration.rb +9 -9
- data/lib/aws-record/record/dirty_tracking.rb +29 -32
- data/lib/aws-record/record/errors.rb +0 -1
- data/lib/aws-record/record/item_collection.rb +4 -4
- data/lib/aws-record/record/item_data.rb +3 -6
- data/lib/aws-record/record/item_operations.rb +77 -93
- data/lib/aws-record/record/key_attributes.rb +0 -2
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/date_marshaler.rb +0 -3
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +1 -2
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +0 -2
- data/lib/aws-record/record/marshalers/float_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +2 -7
- data/lib/aws-record/record/marshalers/list_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/map_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/string_marshaler.rb +1 -4
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +2 -4
- data/lib/aws-record/record/marshalers/time_marshaler.rb +0 -2
- data/lib/aws-record/record/model_attributes.rb +13 -23
- data/lib/aws-record/record/query.rb +6 -9
- data/lib/aws-record/record/secondary_indexes.rb +22 -30
- data/lib/aws-record/record/table_config.rb +51 -62
- data/lib/aws-record/record/table_migration.rb +42 -54
- data/lib/aws-record/record/transactions.rb +32 -35
- data/lib/aws-record/record.rb +29 -37
- metadata +11 -5
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class BooleanMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -36,7 +34,6 @@ module Aws
|
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
39
|
-
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
@@ -5,7 +5,6 @@ require 'date'
|
|
5
5
|
module Aws
|
6
6
|
module Record
|
7
7
|
module Marshalers
|
8
|
-
|
9
8
|
class DateMarshaler
|
10
9
|
def initialize(opts = {})
|
11
10
|
@formatter = opts[:formatter] || Iso8601Formatter
|
@@ -36,7 +35,6 @@ module Aws
|
|
36
35
|
raise ArgumentError, "expected a Date value or nil, got #{date.class}"
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
40
38
|
end
|
41
39
|
|
42
40
|
module Iso8601Formatter
|
@@ -44,7 +42,6 @@ module Aws
|
|
44
42
|
date.iso8601
|
45
43
|
end
|
46
44
|
end
|
47
|
-
|
48
45
|
end
|
49
46
|
end
|
50
47
|
end
|
@@ -5,7 +5,6 @@ require 'date'
|
|
5
5
|
module Aws
|
6
6
|
module Record
|
7
7
|
module Marshalers
|
8
|
-
|
9
8
|
class DateTimeMarshaler
|
10
9
|
def initialize(opts = {})
|
11
10
|
@formatter = opts[:formatter] || Iso8601Formatter
|
@@ -34,6 +33,7 @@ module Aws
|
|
34
33
|
end
|
35
34
|
|
36
35
|
private
|
36
|
+
|
37
37
|
def _format(raw_value)
|
38
38
|
case raw_value
|
39
39
|
when nil
|
@@ -55,7 +55,6 @@ module Aws
|
|
55
55
|
datetime.iso8601
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
59
58
|
end
|
60
59
|
end
|
61
60
|
end
|
@@ -5,7 +5,6 @@ require 'time'
|
|
5
5
|
module Aws
|
6
6
|
module Record
|
7
7
|
module Marshalers
|
8
|
-
|
9
8
|
class EpochTimeMarshaler
|
10
9
|
def initialize(opts = {})
|
11
10
|
@use_local_time = opts[:use_local_time] ? true : false
|
@@ -51,7 +50,6 @@ module Aws
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class FloatMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -17,9 +15,7 @@ module Aws
|
|
17
15
|
when Float
|
18
16
|
raw_value
|
19
17
|
else
|
20
|
-
raw_value.respond_to?(:to_f) ?
|
21
|
-
raw_value.to_f :
|
22
|
-
raw_value.to_s.to_f
|
18
|
+
raw_value.respond_to?(:to_f) ? raw_value.to_f : raw_value.to_s.to_f
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
@@ -35,7 +31,6 @@ module Aws
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
38
|
-
|
39
34
|
end
|
40
35
|
end
|
41
36
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class IntegerMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -17,9 +15,7 @@ module Aws
|
|
17
15
|
when Integer
|
18
16
|
raw_value
|
19
17
|
else
|
20
|
-
raw_value.respond_to?(:to_i) ?
|
21
|
-
raw_value.to_i :
|
22
|
-
raw_value.to_s.to_i
|
18
|
+
raw_value.respond_to?(:to_i) ? raw_value.to_i : raw_value.to_s.to_i
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
@@ -35,7 +31,6 @@ module Aws
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
38
|
-
|
39
34
|
end
|
40
35
|
end
|
41
36
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class ListMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -39,7 +37,6 @@ module Aws
|
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
42
|
-
|
43
40
|
end
|
44
41
|
end
|
45
42
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class MapMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -39,7 +37,6 @@ module Aws
|
|
39
37
|
end
|
40
38
|
end
|
41
39
|
end
|
42
|
-
|
43
40
|
end
|
44
41
|
end
|
45
42
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class NumericSetMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -42,6 +40,7 @@ module Aws
|
|
42
40
|
end
|
43
41
|
|
44
42
|
private
|
43
|
+
|
45
44
|
def _as_numeric(set)
|
46
45
|
set.collect! do |item|
|
47
46
|
if item.is_a?(Numeric)
|
@@ -52,7 +51,6 @@ module Aws
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
55
|
-
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class StringMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -35,7 +33,6 @@ module Aws
|
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
38
|
-
|
39
36
|
end
|
40
37
|
end
|
41
38
|
end
|
@@ -3,10 +3,8 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Marshalers
|
6
|
-
|
7
6
|
class StringSetMarshaler
|
8
|
-
def initialize(opts = {})
|
9
|
-
end
|
7
|
+
def initialize(opts = {}); end
|
10
8
|
|
11
9
|
def type_cast(raw_value)
|
12
10
|
case raw_value
|
@@ -42,6 +40,7 @@ module Aws
|
|
42
40
|
end
|
43
41
|
|
44
42
|
private
|
43
|
+
|
45
44
|
def _as_strings(set)
|
46
45
|
set.collect! do |item|
|
47
46
|
if item.is_a?(String)
|
@@ -52,7 +51,6 @@ module Aws
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
end
|
55
|
-
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
@@ -5,7 +5,6 @@ require 'time'
|
|
5
5
|
module Aws
|
6
6
|
module Record
|
7
7
|
module Marshalers
|
8
|
-
|
9
8
|
class TimeMarshaler
|
10
9
|
def initialize(opts = {})
|
11
10
|
@formatter = opts[:formatter] || Iso8601Formatter
|
@@ -56,7 +55,6 @@ module Aws
|
|
56
55
|
time.iso8601
|
57
56
|
end
|
58
57
|
end
|
59
|
-
|
60
58
|
end
|
61
59
|
end
|
62
60
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
|
-
|
6
5
|
# @api private
|
7
6
|
class ModelAttributes
|
8
7
|
attr_reader :attributes, :storage_attributes
|
@@ -21,7 +20,7 @@ module Aws
|
|
21
20
|
attribute
|
22
21
|
end
|
23
22
|
|
24
|
-
def register_superclass_attribute
|
23
|
+
def register_superclass_attribute(name, attribute)
|
25
24
|
_new_attr_validation(name, attribute)
|
26
25
|
@attributes[name] = attribute.dup
|
27
26
|
@storage_attributes[attribute.database_name] = name
|
@@ -45,6 +44,7 @@ module Aws
|
|
45
44
|
end
|
46
45
|
|
47
46
|
private
|
47
|
+
|
48
48
|
def _new_attr_validation(name, attribute)
|
49
49
|
_validate_attr_name(name)
|
50
50
|
_check_for_naming_collisions(name, attribute.database_name)
|
@@ -53,43 +53,33 @@ module Aws
|
|
53
53
|
|
54
54
|
def _validate_attr_name(name)
|
55
55
|
unless name.is_a?(Symbol)
|
56
|
-
raise ArgumentError
|
56
|
+
raise ArgumentError, 'Must use symbolized :name attribute.'
|
57
57
|
end
|
58
58
|
if @attributes[name]
|
59
|
-
raise Errors::NameCollision
|
60
|
-
"Cannot overwrite existing attribute #{name}"
|
61
|
-
)
|
59
|
+
raise Errors::NameCollision, "Cannot overwrite existing attribute #{name}"
|
62
60
|
end
|
63
61
|
end
|
64
62
|
|
65
63
|
def _check_if_reserved(name)
|
66
64
|
if @model_class.instance_methods.include?(name)
|
67
|
-
raise Errors::ReservedName
|
68
|
-
|
69
|
-
" existing instance method."
|
70
|
-
)
|
65
|
+
raise Errors::ReservedName, "Cannot name an attribute #{name}, that would collide with an"\
|
66
|
+
' existing instance method.'
|
71
67
|
end
|
72
68
|
end
|
73
69
|
|
74
70
|
def _check_for_naming_collisions(name, storage_name)
|
75
71
|
if @attributes[storage_name.to_sym]
|
76
|
-
raise Errors::NameCollision
|
77
|
-
|
78
|
-
" attribute name in #{@attributes}"
|
79
|
-
)
|
72
|
+
raise Errors::NameCollision, "Custom storage name #{storage_name} already exists as an"\
|
73
|
+
" attribute name in #{@attributes}"
|
80
74
|
elsif @storage_attributes[name.to_s]
|
81
|
-
raise Errors::NameCollision
|
82
|
-
|
83
|
-
" name in #{@storage_attributes}"
|
84
|
-
)
|
75
|
+
raise Errors::NameCollision, "Attribute name #{name} already exists as a custom storage"\
|
76
|
+
" name in #{@storage_attributes}"
|
85
77
|
elsif @storage_attributes[storage_name]
|
86
|
-
raise Errors::NameCollision
|
87
|
-
|
88
|
-
|
89
|
-
)
|
78
|
+
raise Errors::NameCollision, "Custom storage name #{storage_name} already in use in"\
|
79
|
+
" #{@storage_attributes}"
|
80
|
+
|
90
81
|
end
|
91
82
|
end
|
92
83
|
end
|
93
|
-
|
94
84
|
end
|
95
85
|
end
|
@@ -3,18 +3,16 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Query
|
6
|
-
|
7
6
|
# @api private
|
8
7
|
def self.included(sub_class)
|
9
8
|
sub_class.extend(QueryClassMethods)
|
10
9
|
end
|
11
10
|
|
12
11
|
module QueryClassMethods
|
13
|
-
|
14
12
|
# This method calls
|
15
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method
|
16
|
-
# populating the +:table_name+ parameter from the model
|
17
|
-
# combining this with the other parameters you provide.
|
13
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#query-instance_method
|
14
|
+
# Aws::DynamoDB::Client#query}, populating the +:table_name+ parameter from the model
|
15
|
+
# class, and combining this with the other parameters you provide.
|
18
16
|
#
|
19
17
|
# @example A query with key and filter expressions:
|
20
18
|
# # Example model class
|
@@ -55,9 +53,9 @@ module Aws
|
|
55
53
|
end
|
56
54
|
|
57
55
|
# This method calls
|
58
|
-
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#scan-instance_method
|
59
|
-
# populating the +:table_name+ parameter from the model
|
60
|
-
# combining this with the other parameters you provide.
|
56
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#scan-instance_method
|
57
|
+
# Aws::DynamoDB::Client#scan}, populating the +:table_name+ parameter from the model
|
58
|
+
# class, and combining this with the other parameters you provide.
|
61
59
|
#
|
62
60
|
# @example A scan with a filter expression:
|
63
61
|
# # Example model class
|
@@ -140,7 +138,6 @@ module Aws
|
|
140
138
|
)
|
141
139
|
end
|
142
140
|
end
|
143
|
-
|
144
141
|
end
|
145
142
|
end
|
146
143
|
end
|
@@ -3,27 +3,24 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module SecondaryIndexes
|
6
|
-
|
7
6
|
# @api private
|
8
7
|
def self.included(sub_class)
|
9
|
-
sub_class.instance_variable_set(
|
10
|
-
sub_class.instance_variable_set(
|
8
|
+
sub_class.instance_variable_set('@local_secondary_indexes', {})
|
9
|
+
sub_class.instance_variable_set('@global_secondary_indexes', {})
|
11
10
|
sub_class.extend(SecondaryIndexesClassMethods)
|
12
|
-
if Aws::Record.extends_record?(sub_class)
|
13
|
-
inherit_indexes(sub_class)
|
14
|
-
end
|
11
|
+
inherit_indexes(sub_class) if Aws::Record.extends_record?(sub_class)
|
15
12
|
end
|
16
13
|
|
17
|
-
private
|
18
14
|
def self.inherit_indexes(klass)
|
19
|
-
superclass_lsi = klass.superclass.instance_variable_get(
|
20
|
-
superclass_gsi = klass.superclass.instance_variable_get(
|
21
|
-
klass.instance_variable_set(
|
22
|
-
klass.instance_variable_set(
|
15
|
+
superclass_lsi = klass.superclass.instance_variable_get('@local_secondary_indexes').dup
|
16
|
+
superclass_gsi = klass.superclass.instance_variable_get('@global_secondary_indexes').dup
|
17
|
+
klass.instance_variable_set('@local_secondary_indexes', superclass_lsi)
|
18
|
+
klass.instance_variable_set('@global_secondary_indexes', superclass_gsi)
|
23
19
|
end
|
24
20
|
|
25
|
-
|
21
|
+
private_class_method :inherit_indexes
|
26
22
|
|
23
|
+
module SecondaryIndexesClassMethods
|
27
24
|
# Creates a local secondary index for the model. Learn more about Local
|
28
25
|
# Secondary Indexes in the
|
29
26
|
# {http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html Amazon DynamoDB Developer Guide}.
|
@@ -64,7 +61,7 @@ module Aws
|
|
64
61
|
global_secondary_indexes[name] = opts
|
65
62
|
end
|
66
63
|
|
67
|
-
# Returns hash of local secondary index names to the index
|
64
|
+
# Returns hash of local secondary index names to the index's attributes.
|
68
65
|
#
|
69
66
|
# *Note*: +local_secondary_indexes+ is inherited from a parent model when {#local_secondary_index}
|
70
67
|
# is explicitly specified in the parent.
|
@@ -74,7 +71,7 @@ module Aws
|
|
74
71
|
@local_secondary_indexes
|
75
72
|
end
|
76
73
|
|
77
|
-
# Returns hash of global secondary index names to the index
|
74
|
+
# Returns hash of global secondary index names to the index's attributes.
|
78
75
|
#
|
79
76
|
# *Note*: +global_secondary_indexes+ is inherited from a parent model when {#global_secondary_index}
|
80
77
|
# is explicitly specified in the parent.
|
@@ -99,6 +96,7 @@ module Aws
|
|
99
96
|
end
|
100
97
|
|
101
98
|
private
|
99
|
+
|
102
100
|
def _migration_format_indexes(indexes)
|
103
101
|
return nil if indexes.empty?
|
104
102
|
mfi = indexes.collect do |name, opts|
|
@@ -116,12 +114,12 @@ module Aws
|
|
116
114
|
|
117
115
|
def _si_key_schema(opts)
|
118
116
|
key_schema = [{
|
119
|
-
key_type:
|
117
|
+
key_type: 'HASH',
|
120
118
|
attribute_name: @attributes.storage_name_for(opts[:hash_key])
|
121
119
|
}]
|
122
120
|
if opts[:range_key]
|
123
121
|
key_schema << {
|
124
|
-
key_type:
|
122
|
+
key_type: 'RANGE',
|
125
123
|
attribute_name: @attributes.storage_name_for(opts[:range_key])
|
126
124
|
}
|
127
125
|
end
|
@@ -132,9 +130,7 @@ module Aws
|
|
132
130
|
if params[:hash_key] && params[:range_key]
|
133
131
|
_validate_attributes_exist(params[:hash_key], params[:range_key])
|
134
132
|
else
|
135
|
-
raise ArgumentError
|
136
|
-
"Local Secondary Indexes require a hash and range key!"
|
137
|
-
)
|
133
|
+
raise ArgumentError, 'Local Secondary Indexes require a hash and range key!'
|
138
134
|
end
|
139
135
|
end
|
140
136
|
|
@@ -146,26 +142,22 @@ module Aws
|
|
146
142
|
_validate_attributes_exist(params[:hash_key])
|
147
143
|
end
|
148
144
|
else
|
149
|
-
raise ArgumentError
|
150
|
-
"Global Secondary Indexes require at least a hash key!"
|
151
|
-
)
|
145
|
+
raise ArgumentError, 'Global Secondary Indexes require at least a hash key!'
|
152
146
|
end
|
153
147
|
end
|
154
148
|
|
155
149
|
def _validate_attributes_exist(*attr_names)
|
156
|
-
missing = attr_names.
|
157
|
-
|
150
|
+
missing = attr_names.reject do |attr_name|
|
151
|
+
@attributes.present?(attr_name)
|
158
152
|
end
|
159
153
|
unless missing.empty?
|
160
|
-
raise ArgumentError.
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
)
|
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.'
|
157
|
+
|
165
158
|
end
|
166
159
|
end
|
167
160
|
end
|
168
|
-
|
169
161
|
end
|
170
162
|
end
|
171
163
|
end
|