ocean-dynamo 0.2.2 → 0.2.3
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/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