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

Sign up to get free protection for your applications and to get access to all the features.
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