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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e20ddd5caa633c5ac1a7acb5e0e6cacfeed52595
|
4
|
+
data.tar.gz: 7317f916341e270b2418d54753a7c0d20540cd7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be783b2361e461595023f044f6147d0bf6935c5a15bbfa585d9cf97b92f63faad4c4d585da6827ec4a93dc1e8581c8e1c7774a400463236695554647a6edb5b0
|
7
|
+
data.tar.gz: 6c22f85ad6a3ca6455d0ac8d04de0bc8849605818605130a430ee7789c47f9088d219f4d363790e6dc3224fc4b22c352b0447b4e61e4be141af7a8295a7f972a
|
data/lib/aws-record.rb
CHANGED
@@ -28,17 +28,17 @@ module Aws
|
|
28
28
|
autoload :TableMigration, 'aws-record/record/table_migration'
|
29
29
|
autoload :VERSION, 'aws-record/record/version'
|
30
30
|
|
31
|
-
module
|
32
|
-
autoload :StringMarshaler,
|
33
|
-
autoload :BooleanMarshaler,
|
34
|
-
autoload :IntegerMarshaler,
|
35
|
-
autoload :FloatMarshaler,
|
36
|
-
autoload :DateMarshaler,
|
37
|
-
autoload :DateTimeMarshaler,
|
38
|
-
autoload :ListMarshaler,
|
39
|
-
autoload :MapMarshaler,
|
40
|
-
autoload :StringSetMarshaler,
|
41
|
-
autoload :NumericSetMarshaler, 'aws-record/record/
|
31
|
+
module Marshalers
|
32
|
+
autoload :StringMarshaler, 'aws-record/record/marshalers/string_marshaler'
|
33
|
+
autoload :BooleanMarshaler, 'aws-record/record/marshalers/boolean_marshaler'
|
34
|
+
autoload :IntegerMarshaler, 'aws-record/record/marshalers/integer_marshaler'
|
35
|
+
autoload :FloatMarshaler, 'aws-record/record/marshalers/float_marshaler'
|
36
|
+
autoload :DateMarshaler, 'aws-record/record/marshalers/date_marshaler'
|
37
|
+
autoload :DateTimeMarshaler, 'aws-record/record/marshalers/date_time_marshaler'
|
38
|
+
autoload :ListMarshaler, 'aws-record/record/marshalers/list_marshaler'
|
39
|
+
autoload :MapMarshaler, 'aws-record/record/marshalers/map_marshaler'
|
40
|
+
autoload :StringSetMarshaler, 'aws-record/record/marshalers/string_set_marshaler'
|
41
|
+
autoload :NumericSetMarshaler, 'aws-record/record/marshalers/numeric_set_marshaler'
|
42
42
|
end
|
43
43
|
|
44
44
|
end
|
data/lib/aws-record/record.rb
CHANGED
@@ -50,6 +50,7 @@ module Aws
|
|
50
50
|
# # Attribute definitions go here...
|
51
51
|
# end
|
52
52
|
def self.included(sub_class)
|
53
|
+
@track_mutations = true
|
53
54
|
sub_class.send(:extend, RecordClassMethods)
|
54
55
|
sub_class.send(:include, Attributes)
|
55
56
|
sub_class.send(:include, ItemOperations)
|
@@ -183,6 +184,26 @@ module Aws
|
|
183
184
|
@dynamodb_client ||= configure_client
|
184
185
|
end
|
185
186
|
|
187
|
+
# Turns off mutation tracking for all attributes in the model.
|
188
|
+
def disable_mutation_tracking
|
189
|
+
@track_mutations = false
|
190
|
+
end
|
191
|
+
|
192
|
+
# Turns on mutation tracking for all attributes in the model. Note that
|
193
|
+
# mutation tracking is on by default, so you generally would not need to
|
194
|
+
# call this. It is provided in case there is a need to dynamically turn
|
195
|
+
# this feature on and off, though that would be generally discouraged and
|
196
|
+
# could cause inaccurate mutation tracking at runtime.
|
197
|
+
def enable_mutation_tracking
|
198
|
+
@track_mutations = true
|
199
|
+
end
|
200
|
+
|
201
|
+
# @return [Boolean] true if mutation tracking is enabled at the model
|
202
|
+
# level, false otherwise.
|
203
|
+
def mutation_tracking_enabled?
|
204
|
+
@track_mutations == false ? false : true
|
205
|
+
end
|
206
|
+
|
186
207
|
private
|
187
208
|
def _user_agent(custom)
|
188
209
|
if custom
|
@@ -21,7 +21,7 @@ module Aws
|
|
21
21
|
# within the model class and item instances.
|
22
22
|
class Attribute
|
23
23
|
|
24
|
-
attr_reader :name, :database_name, :dynamodb_type
|
24
|
+
attr_reader :name, :database_name, :dynamodb_type, :default_value
|
25
25
|
|
26
26
|
# @param [Symbol] name Name of the attribute. It should be a name that is
|
27
27
|
# safe to use as a method.
|
@@ -39,11 +39,27 @@ module Aws
|
|
39
39
|
# "M", "L". Optional if this attribute will never be used for a key or
|
40
40
|
# secondary index, but most convenience methods for setting attributes
|
41
41
|
# will provide this.
|
42
|
+
# @option options [Boolean] :mutation_tracking Optional attribute used to
|
43
|
+
# indicate whether mutations to values should be explicitly tracked when
|
44
|
+
# determining if a value is "dirty". Important for collection types
|
45
|
+
# which are often primarily modified by mutation of a single object
|
46
|
+
# reference. By default, is false.
|
47
|
+
# @option options [Boolean] :persist_nil Optional attribute used to
|
48
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
49
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
50
|
+
# nil values will be ignored and not persisted. By default, is false.
|
51
|
+
# @option options [Object] :default_value Optional attribute used to
|
52
|
+
# define a "default value" to be used if the attribute's value on an
|
53
|
+
# item is nil or not set at persistence time.
|
42
54
|
def initialize(name, options = {})
|
43
55
|
@name = name
|
44
56
|
@database_name = options[:database_attribute_name] || name.to_s
|
45
57
|
@dynamodb_type = options[:dynamodb_type]
|
46
58
|
@marshaler = options[:marshaler] || DefaultMarshaler
|
59
|
+
@mutation_tracking = options[:mutation_tracking]
|
60
|
+
@persist_nil = options[:persist_nil]
|
61
|
+
dv = options[:default_value]
|
62
|
+
@default_value = type_cast(dv) unless dv.nil?
|
47
63
|
end
|
48
64
|
|
49
65
|
# Attempts to type cast a raw value into the attribute's type. This call
|
@@ -52,7 +68,9 @@ module Aws
|
|
52
68
|
# @return [Object] the type cast object. Return type is dependent on the
|
53
69
|
# marshaler used. See your attribute's marshaler class for details.
|
54
70
|
def type_cast(raw_value)
|
55
|
-
@marshaler.type_cast(raw_value)
|
71
|
+
cast_value = @marshaler.type_cast(raw_value)
|
72
|
+
cast_value = default_value if cast_value.nil?
|
73
|
+
cast_value
|
56
74
|
end
|
57
75
|
|
58
76
|
# Attempts to serialize a raw value into the attribute's serialized
|
@@ -62,7 +80,21 @@ module Aws
|
|
62
80
|
# @return [Object] the serialized object. Return type is dependent on the
|
63
81
|
# marshaler used. See your attribute's marshaler class for details.
|
64
82
|
def serialize(raw_value)
|
65
|
-
|
83
|
+
cast_value = type_cast(raw_value)
|
84
|
+
cast_value = default_value if cast_value.nil?
|
85
|
+
@marshaler.serialize(cast_value)
|
86
|
+
end
|
87
|
+
|
88
|
+
# @return [Boolean] true if this attribute should do active mutation
|
89
|
+
# tracking, false otherwise. Default: false
|
90
|
+
def track_mutations?
|
91
|
+
@mutation_tracking ? true : false
|
92
|
+
end
|
93
|
+
|
94
|
+
# @return [Boolean] true if this attribute will actively persist nil
|
95
|
+
# values, false otherwise. Default: false
|
96
|
+
def persist_nil?
|
97
|
+
@persist_nil ? true : false
|
66
98
|
end
|
67
99
|
|
68
100
|
# @api private
|
@@ -87,6 +87,18 @@ module Aws
|
|
87
87
|
# "M", "L". Optional if this attribute will never be used for a key or
|
88
88
|
# secondary index, but most convenience methods for setting attributes
|
89
89
|
# will provide this.
|
90
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
91
|
+
# indicate whether mutations to values should be explicitly tracked
|
92
|
+
# when determining if a value is "dirty". Important for collection
|
93
|
+
# types which are often primarily modified by mutation of a single
|
94
|
+
# object reference. By default, is false.
|
95
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
96
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
97
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
98
|
+
# nil values will be ignored and not persisted. By default, is false.
|
99
|
+
# @option opts [Object] :default_value Optional attribute used to
|
100
|
+
# define a "default value" to be used if the attribute's value on an
|
101
|
+
# item is nil or not set at persistence time.
|
90
102
|
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
91
103
|
# the hash key for the table.
|
92
104
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
@@ -118,9 +130,21 @@ module Aws
|
|
118
130
|
# the hash key for the table.
|
119
131
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
120
132
|
# the range key for the table.
|
133
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
134
|
+
# indicate if mutations to values should be explicitly tracked when
|
135
|
+
# determining if a value is "dirty". Important for collection types
|
136
|
+
# which are often primarily modified by mutation of a single object
|
137
|
+
# reference. By default, is false.
|
138
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
139
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
140
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
141
|
+
# nil values will be ignored and not persisted. By default, is false.
|
142
|
+
# @option opts [Object] :default_value Optional attribute used to
|
143
|
+
# define a "default value" to be used if the attribute's value on an
|
144
|
+
# item is nil or not set at persistence time.
|
121
145
|
def string_attr(name, opts = {})
|
122
146
|
opts[:dynamodb_type] = "S"
|
123
|
-
attr(name,
|
147
|
+
attr(name, Marshalers::StringMarshaler.new(opts), opts)
|
124
148
|
end
|
125
149
|
|
126
150
|
# Define a boolean-type attribute for your model.
|
@@ -132,9 +156,21 @@ module Aws
|
|
132
156
|
# the hash key for the table.
|
133
157
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
134
158
|
# the range key for the table.
|
159
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
160
|
+
# indicate if mutations to values should be explicitly tracked when
|
161
|
+
# determining if a value is "dirty". Important for collection types
|
162
|
+
# which are often primarily modified by mutation of a single object
|
163
|
+
# reference. By default, is false.
|
164
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
165
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
166
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
167
|
+
# nil values will be ignored and not persisted. By default, is false.
|
168
|
+
# @option opts [Object] :default_value Optional attribute used to
|
169
|
+
# define a "default value" to be used if the attribute's value on an
|
170
|
+
# item is nil or not set at persistence time.
|
135
171
|
def boolean_attr(name, opts = {})
|
136
172
|
opts[:dynamodb_type] = "BOOL"
|
137
|
-
attr(name,
|
173
|
+
attr(name, Marshalers::BooleanMarshaler.new(opts), opts)
|
138
174
|
end
|
139
175
|
|
140
176
|
# Define a integer-type attribute for your model.
|
@@ -146,9 +182,21 @@ module Aws
|
|
146
182
|
# the hash key for the table.
|
147
183
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
148
184
|
# the range key for the table.
|
185
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
186
|
+
# indicate if mutations to values should be explicitly tracked when
|
187
|
+
# determining if a value is "dirty". Important for collection types
|
188
|
+
# which are often primarily modified by mutation of a single object
|
189
|
+
# reference. By default, is false.
|
190
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
191
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
192
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
193
|
+
# nil values will be ignored and not persisted. By default, is false.
|
194
|
+
# @option opts [Object] :default_value Optional attribute used to
|
195
|
+
# define a "default value" to be used if the attribute's value on an
|
196
|
+
# item is nil or not set at persistence time.
|
149
197
|
def integer_attr(name, opts = {})
|
150
198
|
opts[:dynamodb_type] = "N"
|
151
|
-
attr(name,
|
199
|
+
attr(name, Marshalers::IntegerMarshaler.new(opts), opts)
|
152
200
|
end
|
153
201
|
|
154
202
|
# Define a float-type attribute for your model.
|
@@ -160,9 +208,21 @@ module Aws
|
|
160
208
|
# the hash key for the table.
|
161
209
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
162
210
|
# the range key for the table.
|
211
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
212
|
+
# indicate if mutations to values should be explicitly tracked when
|
213
|
+
# determining if a value is "dirty". Important for collection types
|
214
|
+
# which are often primarily modified by mutation of a single object
|
215
|
+
# reference. By default, is false.
|
216
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
217
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
218
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
219
|
+
# nil values will be ignored and not persisted. By default, is false.
|
220
|
+
# @option opts [Object] :default_value Optional attribute used to
|
221
|
+
# define a "default value" to be used if the attribute's value on an
|
222
|
+
# item is nil or not set at persistence time.
|
163
223
|
def float_attr(name, opts = {})
|
164
224
|
opts[:dynamodb_type] = "N"
|
165
|
-
attr(name,
|
225
|
+
attr(name, Marshalers::FloatMarshaler.new(opts), opts)
|
166
226
|
end
|
167
227
|
|
168
228
|
# Define a date-type attribute for your model.
|
@@ -174,9 +234,21 @@ module Aws
|
|
174
234
|
# the hash key for the table.
|
175
235
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
176
236
|
# the range key for the table.
|
237
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
238
|
+
# indicate if mutations to values should be explicitly tracked when
|
239
|
+
# determining if a value is "dirty". Important for collection types
|
240
|
+
# which are often primarily modified by mutation of a single object
|
241
|
+
# reference. By default, is false.
|
242
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
243
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
244
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
245
|
+
# nil values will be ignored and not persisted. By default, is false.
|
246
|
+
# @option options [Object] :default_value Optional attribute used to
|
247
|
+
# define a "default value" to be used if the attribute's value on an
|
248
|
+
# item is nil or not set at persistence time.
|
177
249
|
def date_attr(name, opts = {})
|
178
250
|
opts[:dynamodb_type] = "S"
|
179
|
-
attr(name,
|
251
|
+
attr(name, Marshalers::DateMarshaler.new(opts), opts)
|
180
252
|
end
|
181
253
|
|
182
254
|
# Define a datetime-type attribute for your model.
|
@@ -188,9 +260,21 @@ module Aws
|
|
188
260
|
# the hash key for the table.
|
189
261
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
190
262
|
# the range key for the table.
|
263
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
264
|
+
# indicate if mutations to values should be explicitly tracked when
|
265
|
+
# determining if a value is "dirty". Important for collection types
|
266
|
+
# which are often primarily modified by mutation of a single object
|
267
|
+
# reference. By default, is false.
|
268
|
+
# @option opts [Boolean] :persist_nil Optional attribute used to
|
269
|
+
# indicate whether nil values should be persisted. If true, explicitly
|
270
|
+
# set nil values will be saved to DynamoDB as a "null" type. If false,
|
271
|
+
# nil values will be ignored and not persisted. By default, is false.
|
272
|
+
# @option opts [Object] :default_value Optional attribute used to
|
273
|
+
# define a "default value" to be used if the attribute's value on an
|
274
|
+
# item is nil or not set at persistence time.
|
191
275
|
def datetime_attr(name, opts = {})
|
192
276
|
opts[:dynamodb_type] = "S"
|
193
|
-
attr(name,
|
277
|
+
attr(name, Marshalers::DateTimeMarshaler.new(opts), opts)
|
194
278
|
end
|
195
279
|
|
196
280
|
# Define a list-type attribute for your model.
|
@@ -216,16 +300,22 @@ module Aws
|
|
216
300
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
217
301
|
# is safe to use as a method.
|
218
302
|
# @param [Hash] opts
|
219
|
-
# @option opts [Boolean] :nil_as_empty_list Set to true if this
|
220
|
-
# attribute should interpret nil values as an empty list. If false,
|
221
|
-
# nil values will remain nil.
|
222
303
|
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
223
304
|
# the hash key for the table.
|
224
305
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
225
306
|
# the range key for the table.
|
307
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
308
|
+
# indicate if mutations to values should be explicitly tracked when
|
309
|
+
# determining if a value is "dirty". Important for collection types
|
310
|
+
# which are often primarily modified by mutation of a single object
|
311
|
+
# reference. By default, is true.
|
312
|
+
# @option opts [Object] :default_value Optional attribute used to
|
313
|
+
# define a "default value" to be used if the attribute's value on an
|
314
|
+
# item is nil or not set at persistence time.
|
226
315
|
def list_attr(name, opts = {})
|
227
316
|
opts[:dynamodb_type] = "L"
|
228
|
-
|
317
|
+
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
318
|
+
attr(name, Marshalers::ListMarshaler.new(opts), opts)
|
229
319
|
end
|
230
320
|
|
231
321
|
# Define a map-type attribute for your model.
|
@@ -251,16 +341,22 @@ module Aws
|
|
251
341
|
# @param [Symbol] name Name of this attribute. It should be a name that
|
252
342
|
# is safe to use as a method.
|
253
343
|
# @param [Hash] opts
|
254
|
-
# @option opts [Boolean] :nil_as_empty_map Set to true if this
|
255
|
-
# attribute should interpret nil values as an empty hash. If false,
|
256
|
-
# nil values will remain nil.
|
257
344
|
# @option opts [Boolean] :hash_key Set to true if this attribute is
|
258
345
|
# the hash key for the table.
|
259
346
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
260
347
|
# the range key for the table.
|
348
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
349
|
+
# indicate if mutations to values should be explicitly tracked when
|
350
|
+
# determining if a value is "dirty". Important for collection types
|
351
|
+
# which are often primarily modified by mutation of a single object
|
352
|
+
# reference. By default, is true.
|
353
|
+
# @option opts [Object] :default_value Optional attribute used to
|
354
|
+
# define a "default value" to be used if the attribute's value on an
|
355
|
+
# item is nil or not set at persistence time.
|
261
356
|
def map_attr(name, opts = {})
|
262
357
|
opts[:dynamodb_type] = "M"
|
263
|
-
|
358
|
+
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
359
|
+
attr(name, Marshalers::MapMarshaler.new(opts), opts)
|
264
360
|
end
|
265
361
|
|
266
362
|
# Define a string set attribute for your model.
|
@@ -280,9 +376,18 @@ module Aws
|
|
280
376
|
# the hash key for the table.
|
281
377
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
282
378
|
# the range key for the table.
|
379
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
380
|
+
# indicate if mutations to values should be explicitly tracked when
|
381
|
+
# determining if a value is "dirty". Important for collection types
|
382
|
+
# which are often primarily modified by mutation of a single object
|
383
|
+
# reference. By default, is true.
|
384
|
+
# @option opts [Object] :default_value Optional attribute used to
|
385
|
+
# define a "default value" to be used if the attribute's value on an
|
386
|
+
# item is nil or not set at persistence time.
|
283
387
|
def string_set_attr(name, opts = {})
|
284
388
|
opts[:dynamodb_type] = "SS"
|
285
|
-
|
389
|
+
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
390
|
+
attr(name, Marshalers::StringSetMarshaler.new(opts), opts)
|
286
391
|
end
|
287
392
|
|
288
393
|
# Define a numeric set attribute for your model.
|
@@ -302,9 +407,18 @@ module Aws
|
|
302
407
|
# the hash key for the table.
|
303
408
|
# @option opts [Boolean] :range_key Set to true if this attribute is
|
304
409
|
# the range key for the table.
|
410
|
+
# @option opts [Boolean] :mutation_tracking Optional attribute used to
|
411
|
+
# indicate if mutations to values should be explicitly tracked when
|
412
|
+
# determining if a value is "dirty". Important for collection types
|
413
|
+
# which are often primarily modified by mutation of a single object
|
414
|
+
# reference. By default, is true.
|
415
|
+
# @option opts [Object] :default_value Optional attribute used to
|
416
|
+
# define a "default value" to be used if the attribute's value on an
|
417
|
+
# item is nil or not set at persistence time.
|
305
418
|
def numeric_set_attr(name, opts = {})
|
306
419
|
opts[:dynamodb_type] = "NS"
|
307
|
-
|
420
|
+
opts[:mutation_tracking] = true if opts[:mutation_tracking].nil?
|
421
|
+
attr(name, Marshalers::NumericSetMarshaler.new(opts), opts)
|
308
422
|
end
|
309
423
|
|
310
424
|
# @return [Hash] hash of symbolized attribute names to attribute objects
|
@@ -333,6 +447,13 @@ module Aws
|
|
333
447
|
@keys
|
334
448
|
end
|
335
449
|
|
450
|
+
# @param [Symbol] attr_sym The symbolized name of the attribute.
|
451
|
+
# @return [Boolean] true if object mutations are tracked for dirty
|
452
|
+
# checking of that attribute, false if mutations are not tracked.
|
453
|
+
def track_mutations?(attr_sym)
|
454
|
+
mutation_tracking_enabled? && attributes[attr_sym].track_mutations?
|
455
|
+
end
|
456
|
+
|
336
457
|
private
|
337
458
|
def define_attr_methods(name, attribute)
|
338
459
|
define_method(name) do
|
@@ -24,6 +24,7 @@ module Aws
|
|
24
24
|
# @override initialize(*)
|
25
25
|
def initialize(*)
|
26
26
|
@dirty_data = {}
|
27
|
+
@mutation_copies = {}
|
27
28
|
super
|
28
29
|
end
|
29
30
|
|
@@ -44,7 +45,7 @@ module Aws
|
|
44
45
|
# @param [String, Symbol] name The name of the attribute to to check for dirty changes.
|
45
46
|
# @return [Boolean] +true+ if the specified attribute has any dirty changes, +false+ otherwise.
|
46
47
|
def attribute_dirty?(name)
|
47
|
-
@dirty_data.has_key?(name)
|
48
|
+
@dirty_data.has_key?(name) || _mutated?(name)
|
48
49
|
end
|
49
50
|
|
50
51
|
# Returns the original value of the specified attribute.
|
@@ -63,7 +64,11 @@ module Aws
|
|
63
64
|
# @param [String, Symbol] name The name of the attribute to retrieve the original value of.
|
64
65
|
# @return [Object] The original value of the specified attribute.
|
65
66
|
def attribute_was(name)
|
66
|
-
|
67
|
+
if @mutation_copies.has_key?(name)
|
68
|
+
@mutation_copies[name]
|
69
|
+
else
|
70
|
+
attribute_dirty?(name) ? @dirty_data[name] : @data[name]
|
71
|
+
end
|
67
72
|
end
|
68
73
|
|
69
74
|
# Mark that an attribute is changing. This is useful in situations where it is necessary to track that the value of an
|
@@ -107,7 +112,7 @@ module Aws
|
|
107
112
|
|
108
113
|
@dirty_data[name] =
|
109
114
|
begin
|
110
|
-
current_value
|
115
|
+
_deep_copy(current_value)
|
111
116
|
rescue TypeError
|
112
117
|
current_value
|
113
118
|
end
|
@@ -132,6 +137,13 @@ module Aws
|
|
132
137
|
#
|
133
138
|
def clean!
|
134
139
|
@dirty_data.clear
|
140
|
+
self.class.attributes.each do |name, attribute|
|
141
|
+
if self.class.track_mutations?(name)
|
142
|
+
if @data[name]
|
143
|
+
@mutation_copies[name] = _deep_copy(@data[name])
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
135
147
|
end
|
136
148
|
|
137
149
|
# Returns an array with the name of the attributes with dirty changes.
|
@@ -150,7 +162,13 @@ module Aws
|
|
150
162
|
#
|
151
163
|
# @return [Array] The names of attributes with dirty changes.
|
152
164
|
def dirty
|
153
|
-
@dirty_data.keys
|
165
|
+
ret = @dirty_data.keys.dup
|
166
|
+
@mutation_copies.each do |key, value|
|
167
|
+
if @data[key] != value
|
168
|
+
ret << key unless ret.include?(key)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
ret
|
154
172
|
end
|
155
173
|
|
156
174
|
# Returns +true+ if any attributes have dirty changes, +false+ otherwise.
|
@@ -170,7 +188,10 @@ module Aws
|
|
170
188
|
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
171
189
|
# otherwise.
|
172
190
|
def dirty?
|
173
|
-
@dirty_data.size > 0
|
191
|
+
return true if @dirty_data.size > 0
|
192
|
+
@mutation_copies.any? do |name, value|
|
193
|
+
@mutation_copies[name] != @data[name]
|
194
|
+
end
|
174
195
|
end
|
175
196
|
|
176
197
|
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
@@ -188,7 +209,7 @@ module Aws
|
|
188
209
|
|
189
210
|
record = self.class.find(primary_key)
|
190
211
|
|
191
|
-
unless record.nil?
|
212
|
+
unless record.nil?
|
192
213
|
@data = record.instance_variable_get("@data")
|
193
214
|
else
|
194
215
|
raise Errors::NotFound.new("No record found")
|
@@ -217,7 +238,12 @@ module Aws
|
|
217
238
|
def rollback_attribute!(name)
|
218
239
|
return unless attribute_dirty?(name)
|
219
240
|
|
220
|
-
|
241
|
+
if @mutation_copies.has_key?(name)
|
242
|
+
@data[name] = @mutation_copies[name]
|
243
|
+
@dirty_data.delete(name) if @dirty_data.has_key?(name)
|
244
|
+
else
|
245
|
+
@data[name] = @dirty_data.delete(name)
|
246
|
+
end
|
221
247
|
end
|
222
248
|
|
223
249
|
# Restores all attributes to their original values.
|
@@ -252,15 +278,29 @@ module Aws
|
|
252
278
|
#
|
253
279
|
# @override write_attribute(*)
|
254
280
|
def write_attribute(name, attribute, value)
|
281
|
+
_dirty_write_attribute(name, attribute, value)
|
282
|
+
super
|
283
|
+
end
|
284
|
+
|
285
|
+
def _dirty_write_attribute(name, attribute, value)
|
255
286
|
if value == attribute_was(name)
|
256
287
|
@dirty_data.delete(name)
|
257
288
|
else
|
258
289
|
attribute_dirty!(name)
|
259
290
|
end
|
291
|
+
end
|
260
292
|
|
261
|
-
|
293
|
+
def _mutated?(name)
|
294
|
+
if @mutation_copies.has_key?(name)
|
295
|
+
@data[name] != @mutation_copies[name]
|
296
|
+
else
|
297
|
+
false
|
298
|
+
end
|
262
299
|
end
|
263
300
|
|
301
|
+
def _deep_copy(obj)
|
302
|
+
Marshal.load(Marshal.dump(obj))
|
303
|
+
end
|
264
304
|
|
265
305
|
module DirtyTrackingClassMethods
|
266
306
|
|