ocean-dynamo 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +16 -1
- data/lib/ocean-dynamo.rb +0 -6
- data/lib/ocean-dynamo/attributes.rb +4 -8
- data/lib/ocean-dynamo/base.rb +30 -0
- data/lib/ocean-dynamo/class_variables.rb +6 -0
- data/lib/ocean-dynamo/persistence.rb +66 -24
- data/lib/ocean-dynamo/queries.rb +9 -2
- data/lib/ocean-dynamo/schema.rb +8 -2
- data/lib/ocean-dynamo/tables.rb +0 -1
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eaf6828f75761ed94d2acbfa5a28383b892c2d3
|
4
|
+
data.tar.gz: 9cc793dae4769417a4b87949f6c8a183679f6bc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff59c0d44b7c45cdd07702f199b6816f1daedfa9998d0ffe8c6e75f8bff094c46ab55a144e81a57932d8775e758d0af0e378b922815959144294c715e53c3a40
|
7
|
+
data.tar.gz: ea2b09b9afa20d4a0cf0e6e6d0a7e51b739e0674dd06f9fbbf877a903c31a96e3311e00dad45578948b5a0c5601312f65ceb15539de33c73310a1c09f054a49c
|
data/README.rdoc
CHANGED
@@ -72,7 +72,22 @@ Sets are represented as arrays and may not contain duplicates and may not be emp
|
|
72
72
|
All attributes except the :string type can take the value nil. Storing nil for a string
|
73
73
|
value will return the empty string, "".
|
74
74
|
|
75
|
-
Also, dynamo_schema takes args and many options.
|
75
|
+
Also, dynamo_schema takes args and many options. Here's the full syntax:
|
76
|
+
|
77
|
+
dynamo_schema(
|
78
|
+
table_hash_key = :uuid,
|
79
|
+
table_range_key = nil,
|
80
|
+
table_name: compute_table_name,
|
81
|
+
table_name_prefix: nil,
|
82
|
+
table_name_suffix: nil,
|
83
|
+
read_capacity_units: 10,
|
84
|
+
write_capacity_units: 5,
|
85
|
+
connect: :late,
|
86
|
+
create: false,
|
87
|
+
locking: :lock_version,
|
88
|
+
timestamps: [:created_at, :updated_at],
|
89
|
+
&block
|
90
|
+
)
|
76
91
|
|
77
92
|
At the moment, OceanDynamo is fully usable as an ActiveModel and can be used by Rails
|
78
93
|
controllers. Furthermore, OceanDynamo implements much of the infrastructure of ActiveRecord;
|
data/lib/ocean-dynamo.rb
CHANGED
@@ -16,9 +16,7 @@ module OceanDynamo
|
|
16
16
|
write_attribute(name, evaluate_default(md[:default], md[:type]))
|
17
17
|
self.class.class_eval "def #{name}; read_attribute('#{name.to_s}'); end"
|
18
18
|
self.class.class_eval "def #{name}=(value); write_attribute('#{name.to_s}', value); end"
|
19
|
-
|
20
|
-
self.class.class_eval "def #{name}?; read_attribute('#{name.to_s}'); end"
|
21
|
-
end
|
19
|
+
self.class.class_eval "def #{name}?; read_attribute('#{name.to_s}').present?; end"
|
22
20
|
end
|
23
21
|
@dynamo_item = nil
|
24
22
|
@destroyed = false
|
@@ -91,9 +89,7 @@ module OceanDynamo
|
|
91
89
|
# raise ActiveModel::ForbiddenAttributesError
|
92
90
|
# end
|
93
91
|
# end
|
94
|
-
values.each
|
95
|
-
_assign_attribute(k, v)
|
96
|
-
end
|
92
|
+
values.each { |k, v| _assign_attribute(k, v) }
|
97
93
|
end
|
98
94
|
|
99
95
|
|
@@ -197,11 +193,11 @@ module OceanDynamo
|
|
197
193
|
|
198
194
|
def _assign_attribute(k, v) # :nodoc:
|
199
195
|
public_send("#{k}=", v)
|
200
|
-
rescue
|
196
|
+
rescue NoMethodError
|
201
197
|
if respond_to?("#{k}=")
|
202
198
|
raise
|
203
199
|
else
|
204
|
-
raise
|
200
|
+
raise UnknownAttributeError, "unknown attribute: #{k}"
|
205
201
|
end
|
206
202
|
end
|
207
203
|
|
data/lib/ocean-dynamo/base.rb
CHANGED
@@ -4,5 +4,35 @@ module OceanDynamo
|
|
4
4
|
include ActiveModel::Model
|
5
5
|
include ActiveModel::Validations::Callbacks
|
6
6
|
|
7
|
+
|
8
|
+
def ==(comparison_object)
|
9
|
+
super ||
|
10
|
+
comparison_object.instance_of?(self.class) &&
|
11
|
+
id.present? &&
|
12
|
+
comparison_object.id == id
|
13
|
+
end
|
14
|
+
alias :eql? :==
|
15
|
+
|
16
|
+
|
17
|
+
# Clone and freeze the attributes hash such that associations are still
|
18
|
+
# accessible, even on destroyed records, but cloned models will not be
|
19
|
+
# frozen.
|
20
|
+
def freeze
|
21
|
+
@attributes = @attributes.clone.freeze
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns +true+ if the attributes hash has been frozen.
|
26
|
+
def frozen?
|
27
|
+
@attributes.frozen?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Allows sort on objects
|
31
|
+
def <=>(other_object)
|
32
|
+
if other_object.is_a?(self.class)
|
33
|
+
self.to_key <=> other_object.to_key
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
7
37
|
end
|
8
38
|
end
|
@@ -43,5 +43,11 @@ module OceanDynamo
|
|
43
43
|
class_attribute :table_create_policy, instance_writer: false
|
44
44
|
self.table_create_policy = false
|
45
45
|
|
46
|
+
class_attribute :lock_attribute, instance_writer: false
|
47
|
+
self.lock_attribute = :lock_version
|
48
|
+
|
49
|
+
class_attribute :timestamp_attributes, instance_writer: false
|
50
|
+
self.timestamp_attributes = [:created_at, :updated_at]
|
51
|
+
|
46
52
|
end
|
47
53
|
end
|
@@ -108,9 +108,7 @@ module OceanDynamo
|
|
108
108
|
run_callbacks :create do
|
109
109
|
k = read_attribute(table_hash_key)
|
110
110
|
write_attribute(table_hash_key, SecureRandom.uuid) if k == "" || k == nil
|
111
|
-
|
112
|
-
self.created_at ||= t
|
113
|
-
self.updated_at ||= t
|
111
|
+
set_timestamps
|
114
112
|
dynamo_persist
|
115
113
|
true
|
116
114
|
end
|
@@ -124,8 +122,8 @@ module OceanDynamo
|
|
124
122
|
run_callbacks :commit do
|
125
123
|
run_callbacks :save do
|
126
124
|
run_callbacks :update do
|
127
|
-
|
128
|
-
dynamo_persist
|
125
|
+
set_timestamps
|
126
|
+
dynamo_persist(lock: lock_attribute)
|
129
127
|
true
|
130
128
|
end
|
131
129
|
end
|
@@ -148,12 +146,11 @@ module OceanDynamo
|
|
148
146
|
|
149
147
|
|
150
148
|
def delete
|
151
|
-
_connect_late?
|
152
149
|
if persisted?
|
153
|
-
|
150
|
+
dynamo_delete(lock: lock_attribute)
|
154
151
|
end
|
152
|
+
freeze
|
155
153
|
@destroyed = true
|
156
|
-
#freeze
|
157
154
|
end
|
158
155
|
|
159
156
|
|
@@ -167,17 +164,16 @@ module OceanDynamo
|
|
167
164
|
|
168
165
|
def touch(name=nil)
|
169
166
|
raise DynamoError, "can not touch on a new record object" unless persisted?
|
170
|
-
|
167
|
+
_late_connect?
|
171
168
|
run_callbacks :touch do
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
dynamo_item.attributes.update do |u|
|
178
|
-
attrs.each do |k|
|
179
|
-
u.set(k => serialize_attribute(k, t))
|
169
|
+
begin
|
170
|
+
dynamo_item.attributes.update(_handle_locking) do |u|
|
171
|
+
set_timestamps(name).each do |k|
|
172
|
+
u.set(k => serialize_attribute(k, read_attribute(k)))
|
173
|
+
end
|
180
174
|
end
|
175
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
|
176
|
+
raise OceanDynamo::StaleObjectError
|
181
177
|
end
|
182
178
|
self
|
183
179
|
end
|
@@ -187,7 +183,7 @@ module OceanDynamo
|
|
187
183
|
|
188
184
|
protected
|
189
185
|
|
190
|
-
def self.
|
186
|
+
def self._late_connect?
|
191
187
|
return false if table_connected
|
192
188
|
return false unless table_connect_policy
|
193
189
|
establish_db_connection
|
@@ -195,8 +191,8 @@ module OceanDynamo
|
|
195
191
|
end
|
196
192
|
|
197
193
|
|
198
|
-
def
|
199
|
-
self.class.
|
194
|
+
def _late_connect?
|
195
|
+
self.class._late_connect?
|
200
196
|
end
|
201
197
|
|
202
198
|
|
@@ -205,16 +201,33 @@ module OceanDynamo
|
|
205
201
|
end
|
206
202
|
|
207
203
|
|
208
|
-
def dynamo_persist # :nodoc:
|
209
|
-
|
210
|
-
|
204
|
+
def dynamo_persist(lock: nil) # :nodoc:
|
205
|
+
_late_connect?
|
206
|
+
begin
|
207
|
+
options = _handle_locking(lock)
|
208
|
+
@dynamo_item = dynamo_items.put(serialized_attributes, options)
|
209
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
|
210
|
+
raise OceanDynamo::StaleObjectError
|
211
|
+
end
|
212
|
+
|
211
213
|
@new_record = false
|
212
214
|
true
|
213
215
|
end
|
214
216
|
|
215
217
|
|
218
|
+
def dynamo_delete(lock: nil)
|
219
|
+
_late_connect?
|
220
|
+
begin
|
221
|
+
options = _handle_locking(lock)
|
222
|
+
@dynamo_item.delete(options)
|
223
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException
|
224
|
+
raise OceanDynamo::StaleObjectError
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
216
229
|
def dynamo_unpersist(item, consistent) # :nodoc:
|
217
|
-
|
230
|
+
_late_connect?
|
218
231
|
@dynamo_item = item
|
219
232
|
@new_record = false
|
220
233
|
assign_attributes(_dynamo_read_attributes(consistent_read: consistent))
|
@@ -237,5 +250,34 @@ module OceanDynamo
|
|
237
250
|
end
|
238
251
|
|
239
252
|
|
253
|
+
def set_timestamps(name=nil)
|
254
|
+
attrs = []
|
255
|
+
attrs << timestamp_attributes[0] if timestamp_attributes && new_record?
|
256
|
+
attrs << timestamp_attributes[1] if timestamp_attributes
|
257
|
+
attrs << name if name
|
258
|
+
_set_timestamp_attributes(attrs)
|
259
|
+
attrs
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
def _set_timestamp_attributes(attrs)
|
264
|
+
return if attrs.blank?
|
265
|
+
t = Time.zone.now
|
266
|
+
attrs.each { |a| write_attribute a, t }
|
267
|
+
t
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
def _handle_locking(lock=lock_attribute)
|
272
|
+
_late_connect?
|
273
|
+
if lock
|
274
|
+
current_v = read_attribute(lock)
|
275
|
+
write_attribute(lock, current_v+1) unless frozen?
|
276
|
+
{if: {lock => current_v}}
|
277
|
+
else
|
278
|
+
{}
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
240
282
|
end
|
241
283
|
end
|
data/lib/ocean-dynamo/queries.rb
CHANGED
@@ -2,15 +2,22 @@ module OceanDynamo
|
|
2
2
|
class Base
|
3
3
|
|
4
4
|
def self.find(hash, range=nil, consistent: false)
|
5
|
-
|
5
|
+
_late_connect?
|
6
6
|
item = dynamo_items[hash, range]
|
7
7
|
raise RecordNotFound unless item.exists?
|
8
8
|
new.send(:dynamo_unpersist, item, consistent)
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
|
+
def self.find_by_key(*args)
|
13
|
+
find(*args)
|
14
|
+
rescue RecordNotFound
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
|
12
19
|
def self.count
|
13
|
-
|
20
|
+
_late_connect?
|
14
21
|
dynamo_table.item_count || -1 # The || -1 is for fake_dynamo specs.
|
15
22
|
end
|
16
23
|
|
data/lib/ocean-dynamo/schema.rb
CHANGED
@@ -2,7 +2,8 @@ module OceanDynamo
|
|
2
2
|
class Base
|
3
3
|
|
4
4
|
|
5
|
-
def self.dynamo_schema(table_hash_key=:uuid,
|
5
|
+
def self.dynamo_schema(table_hash_key=:uuid,
|
6
|
+
table_range_key=nil,
|
6
7
|
table_name: compute_table_name,
|
7
8
|
table_name_prefix: nil,
|
8
9
|
table_name_suffix: nil,
|
@@ -10,6 +11,8 @@ module OceanDynamo
|
|
10
11
|
write_capacity_units: 5,
|
11
12
|
connect: :late,
|
12
13
|
create: false,
|
14
|
+
locking: :lock_version,
|
15
|
+
timestamps: [:created_at, :updated_at],
|
13
16
|
&block)
|
14
17
|
# Set class vars
|
15
18
|
self.dynamo_client = nil
|
@@ -25,10 +28,13 @@ module OceanDynamo
|
|
25
28
|
self.table_name_suffix = table_name_suffix
|
26
29
|
self.table_read_capacity_units = read_capacity_units
|
27
30
|
self.table_write_capacity_units = write_capacity_units
|
31
|
+
self.lock_attribute = locking
|
32
|
+
self.timestamp_attributes = timestamps
|
28
33
|
# Init
|
29
34
|
self.fields = HashWithIndifferentAccess.new
|
30
35
|
attribute table_hash_key, :string, default: ''
|
31
|
-
|
36
|
+
timestamp_attributes.each { |name| attribute name, :datetime } if timestamp_attributes
|
37
|
+
attribute lock_attribute, :integer, default: 0
|
32
38
|
block.call
|
33
39
|
# Connect to AWS
|
34
40
|
establish_db_connection if connect == true
|
data/lib/ocean-dynamo/tables.rb
CHANGED
data/lib/ocean-dynamo/version.rb
CHANGED