aws-record 1.0.0.pre.3 → 1.0.0.pre.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9169388f2bc16aa254c9c374304bedfdbf9257b9
4
- data.tar.gz: b6e10a6ec3c737436eb9667f84ed4a5235dd33ab
3
+ metadata.gz: 102f5cb13fee3789030badc882c2d171ddb800e8
4
+ data.tar.gz: e4bad779188f59b940492fb2644636901826f41e
5
5
  SHA512:
6
- metadata.gz: 868f158bd20470e096bd40258b5a88670a519637746b95314d0d05a4f9414e05adf631b10904cd99a637a46cd4ba933427f3ef8fd3368c9fbd0d0a8c03c87845
7
- data.tar.gz: 72faa6654ba4a9b66c59b2c20778cbf1d00635e12ee4aef5b1a561d603613fbc49d817b3e2c48246ee41b15a3f51df2fc4074ea6ac5b3a3eaf6b876e1bc1403a
6
+ metadata.gz: a3ef6f71866145568e25d6cac31ebd31c33ad37bfa776ae648e4a0424f69e2e7c6fa46b8d22e5b0c5d5231f1fbde98d1460e5f83e88a812ea85dd4d87e3d3b68
7
+ data.tar.gz: 9cb2cf7a7644a0a6754c7e32452dbf5b83e422e6d7e94ca8a5c0442aa1532ac81ed47519bb00175a1a5e8107f193c1612a0a2ebd3df66a046763daa6c51378a5
data/lib/aws-record.rb CHANGED
@@ -19,6 +19,7 @@ module Aws
19
19
  module Record
20
20
  autoload :Attribute, 'aws-record/record/attribute'
21
21
  autoload :Attributes, 'aws-record/record/attributes'
22
+ autoload :DirtyTracking, 'aws-record/record/dirty_tracking'
22
23
  autoload :Errors, 'aws-record/record/errors'
23
24
  autoload :ItemCollection, 'aws-record/record/item_collection'
24
25
  autoload :ItemOperations, 'aws-record/record/item_operations'
@@ -26,6 +26,7 @@ module Aws
26
26
  sub_class.send(:extend, RecordClassMethods)
27
27
  sub_class.send(:include, Attributes)
28
28
  sub_class.send(:include, ItemOperations)
29
+ sub_class.send(:include, DirtyTracking)
29
30
  sub_class.send(:include, Query)
30
31
  sub_class.send(:include, SecondaryIndexes)
31
32
  end
@@ -33,6 +33,20 @@ module Aws
33
33
  @data.dup
34
34
  end
35
35
 
36
+ private
37
+
38
+ # @private
39
+ def read_attribute(name, attribute)
40
+ raw = @data[name]
41
+ attribute.type_cast(raw)
42
+ end
43
+
44
+ # @private
45
+ def write_attribute(name, attribute, value)
46
+ @data[name] = value
47
+ end
48
+
49
+
36
50
  module ClassMethods
37
51
 
38
52
  # Define an attribute for your model, providing your own attribute type.
@@ -304,12 +318,11 @@ module Aws
304
318
  private
305
319
  def define_attr_methods(name, attribute)
306
320
  define_method(name) do
307
- raw = @data[name]
308
- attribute.type_cast(raw)
321
+ read_attribute(name, attribute)
309
322
  end
310
323
 
311
324
  define_method("#{name}=") do |value|
312
- @data[name] = value
325
+ write_attribute(name, attribute, value)
313
326
  end
314
327
  end
315
328
 
@@ -29,17 +29,9 @@ module Aws
29
29
  when Date
30
30
  raw_value
31
31
  when Integer
32
- begin
33
- Date.parse(Time.at(raw_value).to_s) # assumed timestamp
34
- rescue
35
- nil
36
- end
32
+ Date.parse(Time.at(raw_value).to_s) # assumed timestamp
37
33
  else
38
- begin
39
- Date.parse(raw_value.to_s) # Time, DateTime or String
40
- rescue
41
- nil
42
- end
34
+ Date.parse(raw_value.to_s) # Time, DateTime or String
43
35
  end
44
36
  end
45
37
 
@@ -29,17 +29,9 @@ module Aws
29
29
  when DateTime
30
30
  raw_value
31
31
  when Integer
32
- begin
33
- DateTime.parse(Time.at(raw_value).to_s) # timestamp
34
- rescue
35
- nil
36
- end
32
+ DateTime.parse(Time.at(raw_value).to_s) # timestamp
37
33
  else
38
- begin
39
- DateTime.parse(raw_value.to_s) # Time, Date or String
40
- rescue
41
- nil
42
- end
34
+ DateTime.parse(raw_value.to_s) # Time, Date or String
43
35
  end
44
36
  end
45
37
 
@@ -40,7 +40,7 @@ module Aws
40
40
  elsif float.is_a?(Float)
41
41
  float
42
42
  else
43
- msg = "expected a Float value or nil, got #{value.class}"
43
+ msg = "expected a Float value or nil, got #{float.class}"
44
44
  raise ArgumentError, msg
45
45
  end
46
46
  end
@@ -40,7 +40,7 @@ module Aws
40
40
  elsif integer.is_a?(Integer)
41
41
  integer
42
42
  else
43
- msg = "expected an Integer value or nil, got #{value.class}"
43
+ msg = "expected an Integer value or nil, got #{integer.class}"
44
44
  raise ArgumentError, msg
45
45
  end
46
46
  end
@@ -0,0 +1,302 @@
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 DirtyTracking
17
+
18
+ def self.included(sub_class)
19
+ sub_class.extend(DirtyTrackingClassMethods)
20
+ end
21
+
22
+ # @private
23
+ #
24
+ # @override initialize(*)
25
+ def initialize(*)
26
+ super.tap { @dirty_data = {} }
27
+ end
28
+
29
+ # Returns +true+ if the specified attribute has any dirty changes, +false+ otherwise.
30
+ #
31
+ # @example
32
+ # class Model
33
+ # include Aws::Record
34
+ # integer_attr :id, hash_key: true
35
+ # string_attr :name
36
+ # end
37
+ #
38
+ # model.name_dirty? # => false
39
+ # model.name # => 'Alex'
40
+ # model.name = 'Nick'
41
+ # model.name_dirty? # => true
42
+ #
43
+ # @param [String, Symbol] name The name of the attribute to to check for dirty changes.
44
+ # @return [Boolean] +true+ if the specified attribute has any dirty changes, +false+ otherwise.
45
+ def attribute_dirty?(name)
46
+ @dirty_data.has_key?(name)
47
+ end
48
+
49
+ # Returns the original value of the specified attribute.
50
+ #
51
+ # @example
52
+ # class Model
53
+ # include Aws::Record
54
+ # integer_attr :id, hash_key: true
55
+ # string_attr :name
56
+ # end
57
+ #
58
+ # model.name # => 'Alex'
59
+ # model.name = 'Nick'
60
+ # model.name_was # => 'Alex'
61
+ #
62
+ # @param [String, Symbol] name The name of the attribute to retrieve the original value of.
63
+ # @return [Object] The original value of the specified attribute.
64
+ def attribute_was(name)
65
+ attribute_dirty?(name) ? @dirty_data[name] : @data[name]
66
+ end
67
+
68
+ # Mark that an attribute is changing. This is useful in situations where it is necessary to track that the value of an
69
+ # attribute is changing in-place.
70
+ #
71
+ # @example
72
+ # class Model
73
+ # include Aws::Record
74
+ # integer_attr :id, hash_key: true
75
+ # string_attr :name
76
+ # end
77
+ #
78
+ # model.name # => 'Alex'
79
+ # model.name_dirty? # => false
80
+ # model.name_was # => 'Alex'
81
+ #
82
+ # model.name << 'i'
83
+ # model.name # => 'Alexi'
84
+ #
85
+ # # The change was made in place. Since the String instance representing
86
+ # # the value of name is the same as it was originally, the change is not
87
+ # # detected.
88
+ # model.name_dirty? # => false
89
+ # model.name_was # => 'Alexi'
90
+ #
91
+ # model.name_dirty!
92
+ # model.name_dirty? # => true
93
+ # model.name_was # => 'Alexi'
94
+ #
95
+ # model.name << 's'
96
+ # model.name # => 'Alexis'
97
+ # model.name_dirty? # => true
98
+ # model.name_was # => 'Alexi'
99
+ #
100
+ # @param [String, Symbol] name The name of the attribute to mark as
101
+ # changing.
102
+ def attribute_dirty!(name)
103
+ return if attribute_dirty?(name)
104
+
105
+ current_value = @data[name]
106
+
107
+ @dirty_data[name] =
108
+ begin
109
+ current_value.clone
110
+ rescue TypeError
111
+ current_value
112
+ end
113
+ end
114
+
115
+ # Marks the changes as applied by clearing the current changes and making
116
+ # them accessible through +previous_changes+.
117
+ #
118
+ # # @example
119
+ # class Model
120
+ # include Aws::Record
121
+ # integer_attr :id, hash_key: true
122
+ # string_attr :name
123
+ # end
124
+ #
125
+ # model.name # => 'Alex'
126
+ # model.name = 'Nick'
127
+ # model.dirty? # => true
128
+ #
129
+ # model.clean!
130
+ # model.dirty? # false
131
+ #
132
+ def clean!
133
+ @dirty_data.clear
134
+ end
135
+
136
+ # Returns an array with the name of the attributes with dirty changes.
137
+ #
138
+ # @example
139
+ # class Model
140
+ # include Aws::Record
141
+ # integer_attr :id, hash_key: true
142
+ # string_attr :name
143
+ # end
144
+ #
145
+ # model.dirty # => []
146
+ # model.name # => 'Alex'
147
+ # model.name = 'Nick'
148
+ # model.dirty # => ['name']
149
+ #
150
+ # @return [Array] The names of attributes with dirty changes.
151
+ def dirty
152
+ @dirty_data.keys
153
+ end
154
+
155
+ # Returns +true+ if any attributes have dirty changes, +false+ otherwise.
156
+ #
157
+ # @example
158
+ # class Model
159
+ # include Aws::Record
160
+ # integer_attr :id, hash_key: true
161
+ # string_attr :name
162
+ # end
163
+ #
164
+ # model.dirty? # => false
165
+ # model.name # => 'Alex'
166
+ # model.name = 'Nick'
167
+ # model.dirty? # => true
168
+ #
169
+ # @return [Boolean] +true+ if any attributes have dirty changes, +false+
170
+ # otherwise.
171
+ def dirty?
172
+ @dirty_data.size > 0
173
+ end
174
+
175
+ # Fetches attributes for this instance of an item from Amazon DynamoDB
176
+ # using its primary key and the +find(*)+ class method.
177
+ #
178
+ # @raise [Aws::Record::Errors::NotFound] if no record exists in the
179
+ # database matching the primary key of the item instance.
180
+ #
181
+ # @return [self] Returns the item instance.
182
+ def reload!
183
+ primary_key = self.class.keys.values.inject({}) do |memo, key|
184
+ memo[key] = send(key)
185
+ memo
186
+ end
187
+
188
+ record = self.class.find(primary_key)
189
+
190
+ unless record.nil?
191
+ @data = record.instance_variable_get("@data")
192
+ else
193
+ raise Errors::NotFound.new("No record found")
194
+ end
195
+
196
+ clean!
197
+
198
+ self
199
+ end
200
+
201
+ # Restores the attribute specified to its original value.
202
+ #
203
+ # @example
204
+ # class Model
205
+ # include Aws::Record
206
+ # integer_attr :id, hash_key: true
207
+ # string_attr :name
208
+ # end
209
+ #
210
+ # model.name # => 'Alex'
211
+ # model.name = 'Nick'
212
+ # model.rollback_attribute!(:name)
213
+ # model.name # => 'Alex'
214
+ #
215
+ # @param [String, Symbol] name The name of the attribute to restore
216
+ def rollback_attribute!(name)
217
+ return unless attribute_dirty?(name)
218
+
219
+ @data[name] = @dirty_data.delete(name)
220
+ end
221
+
222
+ # Restores all attributes to their original values.
223
+ #
224
+ # @example
225
+ # class Model
226
+ # include Aws::Record
227
+ # integer_attr :id, hash_key: true
228
+ # string_attr :name
229
+ # end
230
+ #
231
+ # model.name # => 'Alex'
232
+ # model.name = 'Nick'
233
+ # model.rollback!
234
+ # model.name # => 'Alex'
235
+ #
236
+ # @param [Array, String, Symbol] names The names of attributes to restore.
237
+ def rollback!(names = dirty)
238
+ Array(names).each { |name| rollback_attribute!(name) }
239
+ end
240
+
241
+ # @private
242
+ #
243
+ # @override save(*)
244
+ def save(*)
245
+ super.tap { clean! }
246
+ end
247
+
248
+ private
249
+
250
+ # @private
251
+ #
252
+ # @override write_attribute(*)
253
+ def write_attribute(name, attribute, value)
254
+ if value == attribute_was(name)
255
+ @dirty_data.delete(name)
256
+ else
257
+ attribute_dirty!(name)
258
+ end
259
+
260
+ super
261
+ end
262
+
263
+
264
+ module DirtyTrackingClassMethods
265
+
266
+ private
267
+
268
+ # @private
269
+ #
270
+ # @override build_item_from_resp(*)
271
+ def build_item_from_resp(*)
272
+ super.tap { |item| item.clean! }
273
+ end
274
+
275
+ # @private
276
+ #
277
+ # @override define_attr_methods(*)
278
+ def define_attr_methods(name, attribute)
279
+ super.tap do
280
+ define_method("#{name}_dirty?") do
281
+ attribute_dirty?(name)
282
+ end
283
+
284
+ define_method("#{name}_dirty!") do
285
+ attribute_dirty!(name)
286
+ end
287
+
288
+ define_method("#{name}_was") do
289
+ attribute_was(name)
290
+ end
291
+
292
+ define_method("rollback_#{name}!") do
293
+ rollback_attribute!(name)
294
+ end
295
+ end
296
+ end
297
+
298
+ end
299
+
300
+ end
301
+ end
302
+ end
@@ -18,6 +18,7 @@ module Aws
18
18
  class KeyMissing < RuntimeError; end
19
19
  class NameCollision < RuntimeError; end
20
20
  class ReservedName < RuntimeError; end
21
+ class NotFound < RuntimeError; end
21
22
  class InvalidModel < RuntimeError; end
22
23
  class TableDoesNotExist < RuntimeError; end
23
24
 
@@ -13,6 +13,6 @@
13
13
 
14
14
  module Aws
15
15
  module Record
16
- VERSION = "1.0.0.pre.3"
16
+ VERSION = "1.0.0.pre.4"
17
17
  end
18
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.3
4
+ version: 1.0.0.pre.4
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: 2016-02-10 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-resources
@@ -45,6 +45,7 @@ files:
45
45
  - lib/aws-record/record/attributes/numeric_set_marshaler.rb
46
46
  - lib/aws-record/record/attributes/string_marshaler.rb
47
47
  - lib/aws-record/record/attributes/string_set_marshaler.rb
48
+ - lib/aws-record/record/dirty_tracking.rb
48
49
  - lib/aws-record/record/errors.rb
49
50
  - lib/aws-record/record/item_collection.rb
50
51
  - lib/aws-record/record/item_operations.rb