aws-record 1.0.0.pre.8 → 1.0.0.pre.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aws-record.rb +11 -11
- data/lib/aws-record/record.rb +21 -0
- data/lib/aws-record/record/attribute.rb +35 -3
- data/lib/aws-record/record/attributes.rb +137 -16
- data/lib/aws-record/record/dirty_tracking.rb +48 -8
- data/lib/aws-record/record/item_operations.rb +96 -48
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +53 -0
- data/lib/aws-record/record/marshalers/date_marshaler.rb +61 -0
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +72 -0
- data/lib/aws-record/record/marshalers/float_marshaler.rb +52 -0
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +52 -0
- data/lib/aws-record/record/marshalers/list_marshaler.rb +56 -0
- data/lib/aws-record/record/marshalers/map_marshaler.rb +56 -0
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +69 -0
- data/lib/aws-record/record/marshalers/string_marshaler.rb +52 -0
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +69 -0
- data/lib/aws-record/record/version.rb +1 -1
- metadata +12 -13
- data/lib/aws-record/record/attributes/boolean_marshaler.rb +0 -54
- data/lib/aws-record/record/attributes/date_marshaler.rb +0 -54
- data/lib/aws-record/record/attributes/date_time_marshaler.rb +0 -55
- data/lib/aws-record/record/attributes/float_marshaler.rb +0 -53
- data/lib/aws-record/record/attributes/integer_marshaler.rb +0 -53
- data/lib/aws-record/record/attributes/list_marshaler.rb +0 -66
- data/lib/aws-record/record/attributes/map_marshaler.rb +0 -66
- data/lib/aws-record/record/attributes/numeric_set_marshaler.rb +0 -72
- data/lib/aws-record/record/attributes/string_marshaler.rb +0 -60
- data/lib/aws-record/record/attributes/string_set_marshaler.rb +0 -70
@@ -21,17 +21,17 @@ module Aws
|
|
21
21
|
end
|
22
22
|
|
23
23
|
# Saves this instance of an item to Amazon DynamoDB. If this item is "new"
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
24
|
+
# as defined by having new or altered key attributes, will attempt a
|
25
|
+
# conditional
|
26
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method Aws::DynamoDB::Client#put_item}
|
27
|
+
# call, which will not overwrite an existing item. If the item only has
|
28
|
+
# altered non-key attributes, will perform an
|
29
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method Aws::DynamoDB::Client#update_item}
|
30
|
+
# call. Uses this item instance's attributes in order to build the
|
31
|
+
# request on your behalf.
|
32
32
|
#
|
33
33
|
# You can use the +:force+ option to perform a simple put/overwrite
|
34
|
-
#
|
34
|
+
# without conditional validation or update logic.
|
35
35
|
#
|
36
36
|
# @param [Hash] opts
|
37
37
|
# @option opts [Boolean] :force if true, will save as a put operation and
|
@@ -54,17 +54,17 @@ module Aws
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# Saves this instance of an item to Amazon DynamoDB. If this item is "new"
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
57
|
+
# as defined by having new or altered key attributes, will attempt a
|
58
|
+
# conditional
|
59
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#put_item-instance_method Aws::DynamoDB::Client#put_item}
|
60
|
+
# call, which will not overwrite an existing item. If the item only has
|
61
|
+
# altered non-key attributes, will perform an
|
62
|
+
# {http://docs.aws.amazon.com/sdkforruby/api/Aws/DynamoDB/Client.html#update_item-instance_method Aws::DynamoDB::Client#update_item}
|
63
|
+
# call. Uses this item instance's attributes in order to build the
|
64
|
+
# request on your behalf.
|
65
65
|
#
|
66
66
|
# You can use the +:force+ option to perform a simple put/overwrite
|
67
|
-
#
|
67
|
+
# without conditional validation or update logic.
|
68
68
|
#
|
69
69
|
# @param [Hash] opts
|
70
70
|
# @option opts [Boolean] :force if true, will save as a put operation and
|
@@ -112,12 +112,12 @@ module Aws
|
|
112
112
|
if force
|
113
113
|
dynamodb_client.put_item(
|
114
114
|
table_name: self.class.table_name,
|
115
|
-
item:
|
115
|
+
item: _build_item_for_save
|
116
116
|
)
|
117
117
|
elsif expect_new
|
118
118
|
put_opts = {
|
119
119
|
table_name: self.class.table_name,
|
120
|
-
item:
|
120
|
+
item: _build_item_for_save
|
121
121
|
}.merge(prevent_overwrite_expression)
|
122
122
|
begin
|
123
123
|
dynamodb_client.put_item(put_opts)
|
@@ -129,25 +129,52 @@ module Aws
|
|
129
129
|
)
|
130
130
|
end
|
131
131
|
else
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
132
|
+
update_pairs = _dirty_changes_for_update
|
133
|
+
update_tuple = self.class.send(
|
134
|
+
:_build_update_expression,
|
135
|
+
update_pairs
|
136
136
|
)
|
137
|
+
if update_tuple
|
138
|
+
uex, exp_attr_names, exp_attr_values = update_tuple
|
139
|
+
dynamodb_client.update_item(
|
140
|
+
table_name: self.class.table_name,
|
141
|
+
key: key_values,
|
142
|
+
update_expression: uex,
|
143
|
+
expression_attribute_names: exp_attr_names,
|
144
|
+
expression_attribute_values: exp_attr_values
|
145
|
+
)
|
146
|
+
else
|
147
|
+
dynamodb_client.update_item(
|
148
|
+
table_name: self.class.table_name,
|
149
|
+
key: key_values
|
150
|
+
)
|
151
|
+
end
|
137
152
|
end
|
138
153
|
end
|
139
154
|
|
140
|
-
def
|
155
|
+
def _build_item_for_save
|
141
156
|
validate_key_values
|
142
157
|
attributes = self.class.attributes
|
158
|
+
_populate_default_values(attributes)
|
143
159
|
@data.inject({}) do |acc, name_value_pair|
|
144
160
|
attr_name, raw_value = name_value_pair
|
145
|
-
|
146
|
-
|
161
|
+
attribute = attributes[attr_name]
|
162
|
+
if !raw_value.nil? || attribute.persist_nil?
|
163
|
+
db_name = attribute.database_name
|
164
|
+
acc[db_name] = attribute.serialize(raw_value)
|
165
|
+
end
|
147
166
|
acc
|
148
167
|
end
|
149
168
|
end
|
150
169
|
|
170
|
+
def _populate_default_values(attributes)
|
171
|
+
attributes.each do |attr_name, attribute|
|
172
|
+
if !attribute.default_value.nil? && @data[attribute.name].nil?
|
173
|
+
@data[attr_name] = attribute.default_value
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
151
178
|
def key_values
|
152
179
|
validate_key_values
|
153
180
|
attributes = self.class.attributes
|
@@ -198,15 +225,10 @@ module Aws
|
|
198
225
|
}
|
199
226
|
end
|
200
227
|
|
201
|
-
def
|
228
|
+
def _dirty_changes_for_update
|
202
229
|
attributes = self.class.attributes
|
203
230
|
ret = dirty.inject({}) do |acc, attr_name|
|
204
|
-
|
205
|
-
value = {
|
206
|
-
value: attributes[attr_name].serialize(@data[attr_name]),
|
207
|
-
action: "PUT"
|
208
|
-
}
|
209
|
-
acc[key] = value
|
231
|
+
acc[attr_name] = @data[attr_name]
|
210
232
|
acc
|
211
233
|
end
|
212
234
|
ret
|
@@ -289,32 +311,54 @@ module Aws
|
|
289
311
|
table_name: table_name,
|
290
312
|
key: key
|
291
313
|
}
|
292
|
-
|
314
|
+
update_tuple = _build_update_expression(opts)
|
315
|
+
unless update_tuple.nil?
|
316
|
+
uex, exp_attr_names, exp_attr_values = update_tuple
|
317
|
+
request_opts[:update_expression] = uex
|
318
|
+
request_opts[:expression_attribute_names] = exp_attr_names
|
319
|
+
request_opts[:expression_attribute_values] = exp_attr_values
|
320
|
+
end
|
321
|
+
dynamodb_client.update_item(request_opts)
|
322
|
+
end
|
323
|
+
|
324
|
+
private
|
325
|
+
def _build_update_expression(attr_value_pairs)
|
326
|
+
set_expressions = []
|
327
|
+
remove_expressions = []
|
293
328
|
exp_attr_names = {}
|
294
329
|
exp_attr_values = {}
|
295
|
-
name_sub_token = "
|
296
|
-
value_sub_token = "
|
297
|
-
|
330
|
+
name_sub_token = "UE_A"
|
331
|
+
value_sub_token = "ue_a"
|
332
|
+
attr_value_pairs.each do |attr_sym, value|
|
298
333
|
name_sub = "#" + name_sub_token
|
299
334
|
value_sub = ":" + value_sub_token
|
300
335
|
name_sub_token = name_sub_token.succ
|
301
336
|
value_sub_token = value_sub_token.succ
|
302
337
|
|
303
|
-
|
304
|
-
|
338
|
+
attribute = attributes[attr_sym]
|
339
|
+
attr_name = attribute.database_name
|
305
340
|
exp_attr_names[name_sub] = attr_name
|
306
|
-
|
341
|
+
if _update_type_remove?(attribute, value)
|
342
|
+
remove_expressions << "#{name_sub}"
|
343
|
+
else
|
344
|
+
set_expressions << "#{name_sub} = #{value_sub}"
|
345
|
+
exp_attr_values[value_sub] = attribute.serialize(value)
|
346
|
+
end
|
307
347
|
end
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
348
|
+
update_expressions = []
|
349
|
+
unless set_expressions.empty?
|
350
|
+
update_expressions << "SET " + set_expressions.join(", ")
|
351
|
+
end
|
352
|
+
unless remove_expressions.empty?
|
353
|
+
update_expressions << "REMOVE " + remove_expressions.join(", ")
|
354
|
+
end
|
355
|
+
if update_expressions.empty?
|
356
|
+
nil
|
357
|
+
else
|
358
|
+
[update_expressions.join(" "), exp_attr_names, exp_attr_values]
|
313
359
|
end
|
314
|
-
dynamodb_client.update_item(request_opts)
|
315
360
|
end
|
316
361
|
|
317
|
-
private
|
318
362
|
def build_item_from_resp(resp)
|
319
363
|
record = new
|
320
364
|
data = record.instance_variable_get("@data")
|
@@ -323,6 +367,10 @@ module Aws
|
|
323
367
|
end
|
324
368
|
record
|
325
369
|
end
|
370
|
+
|
371
|
+
def _update_type_remove?(attribute, value)
|
372
|
+
value.nil? && !attribute.persist_nil?
|
373
|
+
end
|
326
374
|
end
|
327
375
|
|
328
376
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright 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 Marshalers
|
17
|
+
|
18
|
+
class BooleanMarshaler
|
19
|
+
def initialize(opts = {})
|
20
|
+
end
|
21
|
+
|
22
|
+
def type_cast(raw_value)
|
23
|
+
case raw_value
|
24
|
+
when nil
|
25
|
+
nil
|
26
|
+
when ''
|
27
|
+
nil
|
28
|
+
when false, 'false', '0', 0
|
29
|
+
false
|
30
|
+
else
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def serialize(raw_value)
|
36
|
+
boolean = type_cast(raw_value)
|
37
|
+
case boolean
|
38
|
+
when nil
|
39
|
+
nil
|
40
|
+
when false
|
41
|
+
false
|
42
|
+
when true
|
43
|
+
true
|
44
|
+
else
|
45
|
+
msg = "expected a boolean value or nil, got #{boolean.class}"
|
46
|
+
raise ArgumentError, msg
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Copyright 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
|
+
require 'date'
|
15
|
+
|
16
|
+
module Aws
|
17
|
+
module Record
|
18
|
+
module Marshalers
|
19
|
+
|
20
|
+
class DateMarshaler
|
21
|
+
def initialize(opts = {})
|
22
|
+
@formatter = opts[:formatter] || Iso8601Formatter
|
23
|
+
end
|
24
|
+
|
25
|
+
def type_cast(raw_value)
|
26
|
+
case raw_value
|
27
|
+
when nil
|
28
|
+
nil
|
29
|
+
when ''
|
30
|
+
nil
|
31
|
+
when Date
|
32
|
+
raw_value
|
33
|
+
when Integer
|
34
|
+
Date.parse(Time.at(raw_value).to_s) # assumed timestamp
|
35
|
+
else
|
36
|
+
Date.parse(raw_value.to_s) # Time, DateTime or String
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def serialize(raw_value)
|
41
|
+
date = type_cast(raw_value)
|
42
|
+
if date.nil?
|
43
|
+
nil
|
44
|
+
elsif date.is_a?(Date)
|
45
|
+
@formatter.format(date)
|
46
|
+
else
|
47
|
+
raise ArgumentError, "expected a Date value or nil, got #{date.class}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
module Iso8601Formatter
|
54
|
+
def self.format(date)
|
55
|
+
date.iso8601
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright 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
|
+
require 'date'
|
15
|
+
|
16
|
+
module Aws
|
17
|
+
module Record
|
18
|
+
module Marshalers
|
19
|
+
|
20
|
+
class DateTimeMarshaler
|
21
|
+
def initialize(opts = {})
|
22
|
+
@formatter = opts[:formatter] || Iso8601Formatter
|
23
|
+
@use_local_time = opts[:use_local_time] ? true : false
|
24
|
+
end
|
25
|
+
|
26
|
+
def type_cast(raw_value)
|
27
|
+
value = _format(raw_value)
|
28
|
+
if !@use_local_time && value.is_a?(::DateTime)
|
29
|
+
value.new_offset(0)
|
30
|
+
else
|
31
|
+
value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def serialize(raw_value)
|
36
|
+
datetime = type_cast(raw_value)
|
37
|
+
if datetime.nil?
|
38
|
+
nil
|
39
|
+
elsif datetime.is_a?(::DateTime)
|
40
|
+
@formatter.format(datetime)
|
41
|
+
else
|
42
|
+
msg = "expected a DateTime value or nil, got #{datetime.class}"
|
43
|
+
raise ArgumentError, msg
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def _format(raw_value)
|
49
|
+
case raw_value
|
50
|
+
when nil
|
51
|
+
nil
|
52
|
+
when ''
|
53
|
+
nil
|
54
|
+
when ::DateTime
|
55
|
+
raw_value
|
56
|
+
when Integer # timestamp
|
57
|
+
::DateTime.parse(Time.at(raw_value).to_s)
|
58
|
+
else # Time, Date or String
|
59
|
+
::DateTime.parse(raw_value.to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module Iso8601Formatter
|
65
|
+
def self.format(datetime)
|
66
|
+
datetime.iso8601
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright 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 Marshalers
|
17
|
+
|
18
|
+
class FloatMarshaler
|
19
|
+
def initialize(opts = {})
|
20
|
+
end
|
21
|
+
|
22
|
+
def type_cast(raw_value)
|
23
|
+
case raw_value
|
24
|
+
when nil
|
25
|
+
nil
|
26
|
+
when ''
|
27
|
+
nil
|
28
|
+
when Float
|
29
|
+
raw_value
|
30
|
+
else
|
31
|
+
raw_value.respond_to?(:to_f) ?
|
32
|
+
raw_value.to_f :
|
33
|
+
raw_value.to_s.to_f
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def serialize(raw_value)
|
38
|
+
float = type_cast(raw_value)
|
39
|
+
if float.nil?
|
40
|
+
nil
|
41
|
+
elsif float.is_a?(Float)
|
42
|
+
float
|
43
|
+
else
|
44
|
+
msg = "expected a Float value or nil, got #{float.class}"
|
45
|
+
raise ArgumentError, msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|