aws-record 2.10.1 → 2.12.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 +83 -19
- data/VERSION +1 -1
- data/lib/aws-record/record/attribute.rb +8 -8
- 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 +10 -12
- data/lib/aws-record/record/batch_write.rb +2 -1
- data/lib/aws-record/record/buildable_search.rb +37 -39
- data/lib/aws-record/record/client_configuration.rb +14 -14
- data/lib/aws-record/record/dirty_tracking.rb +29 -40
- data/lib/aws-record/record/errors.rb +11 -2
- data/lib/aws-record/record/item_collection.rb +7 -7
- data/lib/aws-record/record/item_data.rb +13 -17
- data/lib/aws-record/record/item_operations.rb +150 -138
- data/lib/aws-record/record/key_attributes.rb +0 -2
- data/lib/aws-record/record/marshalers/boolean_marshaler.rb +2 -5
- data/lib/aws-record/record/marshalers/date_marshaler.rb +1 -6
- data/lib/aws-record/record/marshalers/date_time_marshaler.rb +2 -5
- data/lib/aws-record/record/marshalers/epoch_time_marshaler.rb +2 -8
- data/lib/aws-record/record/marshalers/float_marshaler.rb +3 -8
- data/lib/aws-record/record/marshalers/integer_marshaler.rb +3 -8
- data/lib/aws-record/record/marshalers/list_marshaler.rb +4 -7
- data/lib/aws-record/record/marshalers/map_marshaler.rb +4 -7
- data/lib/aws-record/record/marshalers/numeric_set_marshaler.rb +7 -9
- data/lib/aws-record/record/marshalers/string_marshaler.rb +1 -2
- data/lib/aws-record/record/marshalers/string_set_marshaler.rb +5 -7
- data/lib/aws-record/record/marshalers/time_marshaler.rb +1 -5
- data/lib/aws-record/record/model_attributes.rb +17 -29
- data/lib/aws-record/record/query.rb +8 -11
- data/lib/aws-record/record/secondary_indexes.rb +40 -51
- data/lib/aws-record/record/table_config.rb +93 -115
- data/lib/aws-record/record/table_migration.rb +56 -72
- data/lib/aws-record/record/transactions.rb +40 -43
- data/lib/aws-record/record/version.rb +1 -1
- data/lib/aws-record/record.rb +36 -44
- metadata +13 -8
@@ -3,22 +3,21 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
class BuildableSearch
|
6
|
-
SUPPORTED_OPERATIONS = [
|
6
|
+
SUPPORTED_OPERATIONS = %i[query scan].freeze
|
7
7
|
|
8
8
|
# This should never be called directly, rather it is called by the
|
9
9
|
# #build_query or #build_scan methods of your aws-record model class.
|
10
10
|
def initialize(opts)
|
11
11
|
operation = opts[:operation]
|
12
12
|
model = opts[:model]
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
13
|
+
raise ArgumentError, "Unsupported operation: #{operation}" unless SUPPORTED_OPERATIONS.include?(operation)
|
14
|
+
|
15
|
+
@operation = operation
|
16
|
+
|
18
17
|
@model = model
|
19
18
|
@params = {}
|
20
|
-
@next_name =
|
21
|
-
@next_value =
|
19
|
+
@next_name = 'BUILDERA'
|
20
|
+
@next_value = 'buildera'
|
22
21
|
end
|
23
22
|
|
24
23
|
# If you are querying or scanning on an index, you can specify it with
|
@@ -41,12 +40,11 @@ module Aws
|
|
41
40
|
# builder method to provide the :total_segments of your parallel scan and
|
42
41
|
# the :segment number of this scan.
|
43
42
|
def parallel_scan(opts)
|
44
|
-
unless @operation == :scan
|
45
|
-
raise ArgumentError.new("parallel_scan is only supported for scans")
|
46
|
-
end
|
43
|
+
raise ArgumentError, 'parallel_scan is only supported for scans' unless @operation == :scan
|
47
44
|
unless opts[:total_segments] && opts[:segment]
|
48
|
-
raise ArgumentError
|
45
|
+
raise ArgumentError, 'Must specify :total_segments and :segment in a parallel scan.'
|
49
46
|
end
|
47
|
+
|
50
48
|
@params[:total_segments] = opts[:total_segments]
|
51
49
|
@params[:segment] = opts[:segment]
|
52
50
|
self
|
@@ -56,9 +54,8 @@ module Aws
|
|
56
54
|
# ascending or descending order on your range key. By default, a query is
|
57
55
|
# run in ascending order.
|
58
56
|
def scan_ascending(b)
|
59
|
-
unless @operation == :query
|
60
|
-
|
61
|
-
end
|
57
|
+
raise ArgumentError, 'scan_ascending is only supported for queries.' unless @operation == :query
|
58
|
+
|
62
59
|
@params[:scan_index_forward] = b
|
63
60
|
self
|
64
61
|
end
|
@@ -90,9 +87,8 @@ module Aws
|
|
90
87
|
# ).complete!
|
91
88
|
# q.to_a # You can use this like any other query result in aws-record
|
92
89
|
def key_expr(statement_str, *subs)
|
93
|
-
unless @operation == :query
|
94
|
-
|
95
|
-
end
|
90
|
+
raise ArgumentError, 'key_expr is only supported for queries.' unless @operation == :query
|
91
|
+
|
96
92
|
names = @params[:expression_attribute_names]
|
97
93
|
if names.nil?
|
98
94
|
@params[:expression_attribute_names] = {}
|
@@ -145,10 +141,10 @@ module Aws
|
|
145
141
|
|
146
142
|
# Allows you to define a projection expression for the values returned by
|
147
143
|
# a query or scan. See
|
148
|
-
# {https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
|
149
|
-
# for more details on projection expressions.
|
150
|
-
# your aws-record model class in a projection expression.
|
151
|
-
# retrieved.
|
144
|
+
# {https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html
|
145
|
+
# the Amazon DynamoDB Developer Guide} for more details on projection expressions.
|
146
|
+
# You can use the symbols from your aws-record model class in a projection expression.
|
147
|
+
# Keys are always retrieved.
|
152
148
|
#
|
153
149
|
# @example Scan with a projection expression:
|
154
150
|
# # Example model class
|
@@ -233,44 +229,46 @@ module Aws
|
|
233
229
|
end
|
234
230
|
|
235
231
|
private
|
232
|
+
|
236
233
|
def _key_pass(statement, names)
|
237
234
|
statement.gsub(/:(\w+)/) do |match|
|
238
|
-
key = match.gsub(':','').to_sym
|
235
|
+
key = match.gsub(':', '').to_sym
|
239
236
|
key_name = @model.attributes.storage_name_for(key)
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
237
|
+
|
238
|
+
raise "No such key #{key}" unless key_name
|
239
|
+
|
240
|
+
sub_name = _next_name
|
241
|
+
|
242
|
+
raise 'Substitution collision!' if names[sub_name]
|
243
|
+
|
244
|
+
names[sub_name] = key_name
|
245
|
+
sub_name
|
248
246
|
end
|
249
247
|
end
|
250
248
|
|
251
249
|
def _apply_values(statement, subs, values)
|
252
250
|
count = 0
|
253
|
-
statement.gsub(/[?]/) do
|
251
|
+
result = statement.gsub(/[?]/) do
|
254
252
|
sub_value = _next_value
|
255
|
-
raise
|
253
|
+
raise 'Substitution collision!' if values[sub_value]
|
254
|
+
|
256
255
|
values[sub_value] = subs[count]
|
257
256
|
count += 1
|
258
257
|
sub_value
|
259
|
-
end
|
260
|
-
|
261
|
-
|
262
|
-
end
|
258
|
+
end
|
259
|
+
result.tap do
|
260
|
+
raise "Expected #{count} values in the substitution set, but found #{subs.size}" unless count == subs.size
|
263
261
|
end
|
264
262
|
end
|
265
263
|
|
266
264
|
def _next_name
|
267
|
-
ret = "
|
265
|
+
ret = "##{@next_name}"
|
268
266
|
@next_name = @next_name.next
|
269
267
|
ret
|
270
268
|
end
|
271
269
|
|
272
270
|
def _next_value
|
273
|
-
ret = "
|
271
|
+
ret = ":#{@next_value}"
|
274
272
|
@next_value = @next_value.next
|
275
273
|
ret
|
276
274
|
end
|
@@ -10,7 +10,7 @@ module Aws
|
|
10
10
|
# attempt to perform an operation against the remote end, if you have not
|
11
11
|
# already configured a client. As such, please read and understand the
|
12
12
|
# documentation in the AWS SDK for Ruby around
|
13
|
-
# {http://docs.aws.amazon.com/
|
13
|
+
# {http://docs.aws.amazon.com/sdk-for-ruby/v3/api/index.html#Configuration configuration}
|
14
14
|
# to ensure you understand how default configuration behavior works. When
|
15
15
|
# in doubt, call this method to ensure your client is configured the way
|
16
16
|
# you want it to be configured.
|
@@ -20,16 +20,19 @@ module Aws
|
|
20
20
|
# @param [Hash] opts the options you wish to use to create the client.
|
21
21
|
# Note that if you include the option +:client+, all other options
|
22
22
|
# will be ignored. See the documentation for other options in the
|
23
|
-
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#initialize-instance_method
|
23
|
+
# {https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/DynamoDB/Client.html#initialize-instance_method
|
24
|
+
# AWS SDK for Ruby}.
|
24
25
|
# @option opts [Aws::DynamoDB::Client] :client allows you to pass in your
|
25
26
|
# own pre-configured client.
|
26
27
|
def configure_client(opts = {})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
# rubocop:disable Style/RedundantSelf
|
29
|
+
@dynamodb_client = if self.class != Module && Aws::Record.extends_record?(self) && opts.empty? &&
|
30
|
+
self.superclass.instance_variable_get('@dynamodb_client')
|
31
|
+
self.superclass.instance_variable_get('@dynamodb_client')
|
32
|
+
else
|
33
|
+
_build_client(opts)
|
34
|
+
end
|
35
|
+
# rubocop:enable Style/RedundantSelf
|
33
36
|
end
|
34
37
|
|
35
38
|
# Gets the
|
@@ -50,12 +53,9 @@ module Aws
|
|
50
53
|
|
51
54
|
def _build_client(opts = {})
|
52
55
|
provided_client = opts.delete(:client)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
def _user_agent(custom)
|
58
|
-
custom || " aws-record/#{VERSION}"
|
56
|
+
client = provided_client || Aws::DynamoDB::Client.new(opts)
|
57
|
+
client.config.user_agent_frameworks << 'aws-record'
|
58
|
+
client
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module DirtyTracking
|
6
|
-
|
7
6
|
def self.included(sub_class)
|
8
7
|
sub_class.extend(DirtyTrackingClassMethods)
|
9
8
|
end
|
@@ -26,7 +25,7 @@ module Aws
|
|
26
25
|
# @return [Boolean] +true+ if the specified attribute has any dirty changes, +false+ otherwise.
|
27
26
|
def attribute_dirty?(name)
|
28
27
|
@data.attribute_dirty?(name)
|
29
|
-
end
|
28
|
+
end
|
30
29
|
|
31
30
|
# Returns the original value of the specified attribute.
|
32
31
|
#
|
@@ -39,7 +38,7 @@ module Aws
|
|
39
38
|
#
|
40
39
|
# model.name # => 'Alex'
|
41
40
|
# model.name = 'Nick'
|
42
|
-
# model.name_was # => 'Alex'
|
41
|
+
# model.name_was # => 'Alex'
|
43
42
|
#
|
44
43
|
# @param [String, Symbol] name The name of the attribute to retrieve the original value of.
|
45
44
|
# @return [Object] The original value of the specified attribute.
|
@@ -47,8 +46,9 @@ module Aws
|
|
47
46
|
@data.attribute_was(name)
|
48
47
|
end
|
49
48
|
|
50
|
-
# Mark that an attribute is changing. This is useful in situations
|
51
|
-
#
|
49
|
+
# Mark that an attribute is changing. This is useful in situations
|
50
|
+
# where it is necessary to track that the value of an
|
51
|
+
# attribute is changing in-place.
|
52
52
|
#
|
53
53
|
# @example
|
54
54
|
# class Model
|
@@ -63,9 +63,9 @@ module Aws
|
|
63
63
|
#
|
64
64
|
# model.name << 'i'
|
65
65
|
# model.name # => 'Alexi'
|
66
|
-
#
|
67
|
-
# # The change was made in place. Since the String instance representing
|
68
|
-
# # the value of name is the same as it was originally, the change is not
|
66
|
+
#
|
67
|
+
# # The change was made in place. Since the String instance representing
|
68
|
+
# # the value of name is the same as it was originally, the change is not
|
69
69
|
# # detected.
|
70
70
|
# model.name_dirty? # => false
|
71
71
|
# model.name_was # => 'Alexi'
|
@@ -79,7 +79,7 @@ module Aws
|
|
79
79
|
# model.name_dirty? # => true
|
80
80
|
# model.name_was # => 'Alexi'
|
81
81
|
#
|
82
|
-
# @param [String, Symbol] name The name of the attribute to mark as
|
82
|
+
# @param [String, Symbol] name The name of the attribute to mark as
|
83
83
|
# changing.
|
84
84
|
def attribute_dirty!(name)
|
85
85
|
@data.attribute_dirty!(name)
|
@@ -118,7 +118,7 @@ module Aws
|
|
118
118
|
# model.name = 'Nick'
|
119
119
|
# model.dirty? # => true
|
120
120
|
#
|
121
|
-
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
121
|
+
# @return [Boolean] +true+ if any attributes have dirty changes, +false+
|
122
122
|
# otherwise.
|
123
123
|
def dirty?
|
124
124
|
@data.dirty?
|
@@ -140,7 +140,7 @@ module Aws
|
|
140
140
|
# model.delete!
|
141
141
|
# model.persisted? # => false
|
142
142
|
#
|
143
|
-
# @return [Boolean] +true+ if the model is not new and has not been deleted, +false+
|
143
|
+
# @return [Boolean] +true+ if the model is not new and has not been deleted, +false+
|
144
144
|
# otherwise.
|
145
145
|
def persisted?
|
146
146
|
@data.persisted?
|
@@ -160,7 +160,7 @@ module Aws
|
|
160
160
|
# model.save
|
161
161
|
# model.new_record? # => false
|
162
162
|
#
|
163
|
-
# @return [Boolean] +true+ if the model is newly initialized, +false+
|
163
|
+
# @return [Boolean] +true+ if the model is newly initialized, +false+
|
164
164
|
# otherwise.
|
165
165
|
def new_record?
|
166
166
|
@data.new_record?
|
@@ -179,35 +179,33 @@ module Aws
|
|
179
179
|
# model.destroyed? # => false
|
180
180
|
# model.save
|
181
181
|
# model.destroyed? # => false
|
182
|
-
# model.delete!
|
182
|
+
# model.delete!
|
183
183
|
# model.destroyed? # => true
|
184
184
|
#
|
185
|
-
# @return [Boolean] +true+ if the model has been destroyed, +false+
|
185
|
+
# @return [Boolean] +true+ if the model has been destroyed, +false+
|
186
186
|
# otherwise.
|
187
187
|
def destroyed?
|
188
188
|
@data.destroyed?
|
189
189
|
end
|
190
190
|
|
191
|
-
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
191
|
+
# Fetches attributes for this instance of an item from Amazon DynamoDB
|
192
192
|
# using its primary key and the +find(*)+ class method.
|
193
193
|
#
|
194
|
-
# @raise [Aws::Record::Errors::NotFound] if no record exists in the
|
194
|
+
# @raise [Aws::Record::Errors::NotFound] if no record exists in the
|
195
195
|
# database matching the primary key of the item instance.
|
196
|
-
|
196
|
+
|
197
197
|
# @return [self] Returns the item instance.
|
198
198
|
def reload!
|
199
|
-
primary_key = self.class.keys.values.
|
199
|
+
primary_key = self.class.keys.values.each_with_object({}) do |key, memo|
|
200
200
|
memo[key] = send(key)
|
201
|
-
memo
|
201
|
+
memo
|
202
202
|
end
|
203
203
|
|
204
204
|
record = self.class.find(primary_key)
|
205
205
|
|
206
|
-
unless record.
|
207
|
-
|
208
|
-
|
209
|
-
raise Errors::NotFound.new("No record found")
|
210
|
-
end
|
206
|
+
raise Errors::NotFound, 'No record found' unless record.present?
|
207
|
+
|
208
|
+
@data = record.instance_variable_get('@data')
|
211
209
|
|
212
210
|
clean!
|
213
211
|
|
@@ -247,7 +245,7 @@ module Aws
|
|
247
245
|
# model.rollback!
|
248
246
|
# model.name # => 'Alex'
|
249
247
|
#
|
250
|
-
# @param [Array, String, Symbol] names The names of attributes to restore.
|
248
|
+
# @param [Array, String, Symbol] names The names of attributes to restore.
|
251
249
|
def rollback!(names = dirty)
|
252
250
|
Array(names).each { |name| rollback_attribute!(name) }
|
253
251
|
end
|
@@ -258,48 +256,39 @@ module Aws
|
|
258
256
|
end
|
259
257
|
|
260
258
|
# @private
|
261
|
-
#
|
262
|
-
# @override save(*)
|
263
259
|
def save(*)
|
264
260
|
super.tap { clean! }
|
265
261
|
end
|
266
262
|
|
267
263
|
module DirtyTrackingClassMethods
|
268
|
-
|
269
264
|
private
|
270
265
|
|
271
266
|
# @private
|
272
|
-
#
|
273
|
-
# @override build_item_from_resp(*)
|
274
267
|
def build_item_from_resp(*)
|
275
|
-
super.tap
|
268
|
+
super.tap(&:clean!)
|
276
269
|
end
|
277
270
|
|
278
271
|
# @private
|
279
|
-
#
|
280
|
-
# @override define_attr_methods(*)
|
281
272
|
def _define_attr_methods(name)
|
282
|
-
super.tap do
|
283
|
-
define_method("#{name}_dirty?") do
|
273
|
+
super.tap do
|
274
|
+
define_method("#{name}_dirty?") do
|
284
275
|
attribute_dirty?(name)
|
285
276
|
end
|
286
277
|
|
287
|
-
define_method("#{name}_dirty!") do
|
278
|
+
define_method("#{name}_dirty!") do
|
288
279
|
attribute_dirty!(name)
|
289
280
|
end
|
290
281
|
|
291
|
-
define_method("#{name}_was") do
|
282
|
+
define_method("#{name}_was") do
|
292
283
|
attribute_was(name)
|
293
284
|
end
|
294
285
|
|
295
|
-
define_method("rollback_#{name}!") do
|
286
|
+
define_method("rollback_#{name}!") do
|
296
287
|
rollback_attribute!(name)
|
297
288
|
end
|
298
289
|
end
|
299
290
|
end
|
300
|
-
|
301
291
|
end
|
302
|
-
|
303
292
|
end
|
304
293
|
end
|
305
294
|
end
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
5
|
module Errors
|
6
|
-
|
7
6
|
# RecordErrors relate to the persistence of items. They include both
|
8
7
|
# client errors and certain validation errors.
|
9
8
|
class RecordError < RuntimeError; end
|
@@ -17,7 +16,17 @@ module Aws
|
|
17
16
|
class NotFound < RecordError; end
|
18
17
|
|
19
18
|
# Raised when a conditional write fails.
|
20
|
-
|
19
|
+
# Provides access to the original ConditionalCheckFailedException error
|
20
|
+
# which may have item data if the return values option was used.
|
21
|
+
class ConditionalWriteFailed < RecordError
|
22
|
+
def initialize(message, original_error)
|
23
|
+
@original_error = original_error
|
24
|
+
super(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Aws::DynamoDB::Errors::ConditionalCheckFailedException]
|
28
|
+
attr_reader :original_error
|
29
|
+
end
|
21
30
|
|
22
31
|
# Raised when a validation hook call to +:valid?+ fails.
|
23
32
|
class ValidationError < RecordError; end
|
@@ -27,12 +27,11 @@ module Aws
|
|
27
27
|
# into items on your behalf.
|
28
28
|
def each(&block)
|
29
29
|
return enum_for(:each) unless block_given?
|
30
|
+
|
30
31
|
items.each_page do |page|
|
31
32
|
@last_evaluated_key = page.last_evaluated_key
|
32
33
|
items_array = _build_items_from_response(page.items, @model)
|
33
|
-
items_array.each
|
34
|
-
yield item
|
35
|
-
end
|
34
|
+
items_array.each(&block)
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
@@ -72,19 +71,21 @@ module Aws
|
|
72
71
|
# otherwise.
|
73
72
|
def empty?
|
74
73
|
items.each_page do |page|
|
75
|
-
return false
|
74
|
+
return false unless page.items.empty?
|
76
75
|
end
|
77
76
|
true
|
78
77
|
end
|
79
78
|
|
80
79
|
private
|
80
|
+
|
81
81
|
def _build_items_from_response(items, model)
|
82
82
|
ret = []
|
83
83
|
items.each do |item|
|
84
84
|
model_class = @model_filter ? @model_filter.call(item) : model
|
85
85
|
next unless model_class
|
86
|
+
|
86
87
|
record = model_class.new
|
87
|
-
data = record.instance_variable_get(
|
88
|
+
data = record.instance_variable_get('@data')
|
88
89
|
model_class.attributes.attributes.each do |name, attr|
|
89
90
|
data.set_attribute(name, attr.extract(item))
|
90
91
|
end
|
@@ -96,9 +97,8 @@ module Aws
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def items
|
99
|
-
@
|
100
|
+
@items ||= @client.send(@search_method, @search_params)
|
100
101
|
end
|
101
|
-
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module Aws
|
4
4
|
module Record
|
5
|
-
|
6
5
|
# @api private
|
7
6
|
class ItemData
|
8
7
|
def initialize(model_attributes, opts)
|
@@ -17,7 +16,6 @@ module Aws
|
|
17
16
|
|
18
17
|
populate_default_values
|
19
18
|
end
|
20
|
-
|
21
19
|
attr_accessor :new_record, :destroyed
|
22
20
|
|
23
21
|
def get_attribute(name)
|
@@ -49,11 +47,11 @@ module Aws
|
|
49
47
|
@model_attributes.attributes.each_key do |name|
|
50
48
|
populate_default_values
|
51
49
|
value = get_attribute(name)
|
52
|
-
if @track_mutations
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
@clean_copies[name] = if @track_mutations
|
51
|
+
_deep_copy(value)
|
52
|
+
else
|
53
|
+
value
|
54
|
+
end
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
@@ -75,14 +73,14 @@ module Aws
|
|
75
73
|
end
|
76
74
|
|
77
75
|
def dirty
|
78
|
-
@model_attributes.attributes.keys.
|
76
|
+
@model_attributes.attributes.keys.each_with_object([]) do |name, acc|
|
79
77
|
acc << name if attribute_dirty?(name)
|
80
78
|
acc
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
84
82
|
def dirty?
|
85
|
-
dirty.empty?
|
83
|
+
!dirty.empty?
|
86
84
|
end
|
87
85
|
|
88
86
|
def rollback_attribute!(name)
|
@@ -98,7 +96,7 @@ module Aws
|
|
98
96
|
end
|
99
97
|
|
100
98
|
def build_save_hash
|
101
|
-
@data.
|
99
|
+
@data.each_with_object({}) do |name_value_pair, acc|
|
102
100
|
attr_name, raw_value = name_value_pair
|
103
101
|
attribute = @model_attributes.attribute_for(attr_name)
|
104
102
|
if !raw_value.nil? || attribute.persist_nil?
|
@@ -111,20 +109,18 @@ module Aws
|
|
111
109
|
|
112
110
|
def populate_default_values
|
113
111
|
@model_attributes.attributes.each do |name, attribute|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
112
|
+
next if (default_value = attribute.default_value).nil?
|
113
|
+
next unless @data[name].nil?
|
114
|
+
|
115
|
+
@data[name] = default_value
|
119
116
|
end
|
120
117
|
end
|
121
118
|
|
122
119
|
private
|
120
|
+
|
123
121
|
def _deep_copy(obj)
|
124
122
|
Marshal.load(Marshal.dump(obj))
|
125
123
|
end
|
126
|
-
|
127
124
|
end
|
128
|
-
|
129
125
|
end
|
130
126
|
end
|