ocean-dynamo 1.2.4 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +18 -27
- data/lib/ocean-dynamo/associations/association.rb +6 -4
- data/lib/ocean-dynamo/associations/associations.rb +10 -0
- data/lib/ocean-dynamo/associations/belongs_to.rb +1 -1
- data/lib/ocean-dynamo/associations/collection_association.rb +7 -5
- data/lib/ocean-dynamo/associations/collection_proxy.rb +2 -3
- data/lib/ocean-dynamo/associations/has_many.rb +10 -4
- data/lib/ocean-dynamo/associations/relation.rb +0 -1
- data/lib/ocean-dynamo/attributes.rb +1 -0
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +18 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e5d649565fd30bee32f1b8d80c7f6117009229e
|
4
|
+
data.tar.gz: e281cb72d49607d53e9ddd7053462f50c29b0604
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf608c59e414e273d9e13cf30070e3e2c3ba6ef79e343900b66d7fc1dbc08dd903332fe9297310fbebb5dbc1c9050957130178fe864dafc316ced76e397c629c
|
7
|
+
data.tar.gz: 708e7170927244786d84e20bc2b7ffc99206263d210f3fe4e73ee4306be3bb659b1383b01cb9631b91ef85c4d378a03947a28b3a4cb60f3f5dbbf896c99c34cf
|
data/README.rdoc
CHANGED
@@ -40,16 +40,16 @@ with FactoryGirl.
|
|
40
40
|
|
41
41
|
=== Future milestones
|
42
42
|
|
43
|
-
*
|
43
|
+
* Direct support for the DynamoDB JSON attribute types for arrays and hashes
|
44
|
+
* Collection proxies, to implement ActiveRecord-style method chaining, e.g.:
|
44
45
|
<code>blog_entry.comments.build(body: "Cool!").save!</code>
|
45
46
|
* The +has_and_belongs_to_many+ assocation.
|
46
|
-
* A generator to install the <tt>config/aws.yml</tt> file.
|
47
47
|
|
48
48
|
|
49
49
|
=== Current use
|
50
50
|
|
51
51
|
OceanDynamo is used as a central component in Ocean, a Rails framework and development
|
52
|
-
pipeline for creating
|
52
|
+
pipeline for creating massively scalable HATEOAS microservice SOAs in the cloud.
|
53
53
|
* http://wiki.oceanframework.net
|
54
54
|
|
55
55
|
Ocean uses OceanDynamo to implement highly scalable job queues and authentication.
|
@@ -99,6 +99,8 @@ The following example shows the basic syntax for declaring a DynamoDB-based sche
|
|
99
99
|
attribute :succeeded, :boolean, default: false
|
100
100
|
attribute :failed, :boolean, default: false
|
101
101
|
attribute :poison, :boolean, default: false
|
102
|
+
|
103
|
+
global_secondary_index :token, projection: :all
|
102
104
|
end
|
103
105
|
|
104
106
|
end
|
@@ -210,13 +212,9 @@ which means that secondary indices won't be necessary for the vast majority of
|
|
210
212
|
DynamoDB tables. This ultimately means reduced operational costs, as well as
|
211
213
|
reduced complexity.
|
212
214
|
|
213
|
-
Nevertheless, as we now have switched to v2 of the DynamoDB API, we will be adding
|
214
|
-
the possibility to define both local and secondary indices for Tables.
|
215
215
|
|
216
216
|
== Secondary Indices
|
217
217
|
|
218
|
-
We now have support for secondary indices.
|
219
|
-
|
220
218
|
=== Local Secondary Indices
|
221
219
|
|
222
220
|
Up to five attributes can be declared as local secondary indices, in the following manner:
|
@@ -242,9 +240,9 @@ combination of keys. Secondary indices don't require the range key to be unique
|
|
242
240
|
the same hash key. This means that secondary index searches always will return a
|
243
241
|
collection.
|
244
242
|
|
245
|
-
|
246
|
-
|
247
|
-
|
243
|
+
Local secondary indices are queried through +find_local_each+ and +find_local+.
|
244
|
+
They take the same arguments; the former yields to a block for each item,
|
245
|
+
the other returns all items in an array.
|
248
246
|
|
249
247
|
The following finds all Authentications where +:username+ is "joe" and +:token+ is "quux":
|
250
248
|
|
@@ -259,9 +257,6 @@ The same thing but with the only the item with the highest token value:
|
|
259
257
|
Authentication.find_local(:username, "joe", :token, ">=", "0",
|
260
258
|
scan_index_forward: false, limit: 1)
|
261
259
|
|
262
|
-
For more information, see the documentation for
|
263
|
-
+find_local_each+ and +find_local+.
|
264
|
-
|
265
260
|
|
266
261
|
=== Global Secondary Indices
|
267
262
|
|
@@ -282,37 +277,34 @@ block:
|
|
282
277
|
end
|
283
278
|
end
|
284
279
|
|
285
|
-
Each +global_secondary_index+ clause
|
280
|
+
Each +global_secondary_index+ clause (there can be a maximum of 5 per table) takes
|
281
|
+
the following arguments:
|
286
282
|
* +hash_value+ (required),
|
287
283
|
* +range_value+ (optional),
|
288
|
-
* +:projection+ (default
|
284
|
+
* +:projection+ (default +:keys_only+, +:all+ for all attributes)
|
289
285
|
* +:read_capacity_units+ (defaults to the table's read capacity, normally 10)
|
290
286
|
* +:write_capacity_units+ (default to the table's write capacity, normally 5)
|
291
287
|
|
292
|
-
|
293
|
-
|
294
|
-
|
288
|
+
Global secondary indices are queried through +find_global_each+ and +find_global+.
|
289
|
+
They take the same arguments; the former yields to a block for each item,
|
290
|
+
the other returns all items in an array.
|
295
291
|
|
296
|
-
The following finds all Authentications whose +:token+ is "quux"
|
292
|
+
The following finds all Authentications whose +:token+ is +"quux"+:
|
297
293
|
|
298
294
|
Authentication.find_global(:token, "quux")
|
299
295
|
|
300
|
-
This retrieves all Authentications belonging to the user with the ID "dfstw-ruyhdf-ewijf"
|
296
|
+
This retrieves all Authentications belonging to the user with the ID +"dfstw-ruyhdf-ewijf"+,
|
301
297
|
sorted in ascending order of the +:expires_at+ attribute:
|
302
298
|
|
303
299
|
Authentication.find_global(:api_user_id, "dfstw-ruyhdf-ewijf",
|
304
300
|
:expires_at, ">=", 0)
|
305
301
|
|
306
|
-
To get the highest +:expires_at+ record
|
302
|
+
To get the highest +:expires_at+ record:
|
307
303
|
|
308
304
|
Authentication.find_global(:api_user_id, "dfstw-ruyhdf-ewijf",
|
309
305
|
:expires_at, ">=", 0,
|
310
306
|
scan_index_forward: false, limit: 1)
|
311
307
|
|
312
|
-
The combination of hash and range key must have been explicitly declared using
|
313
|
-
+global_secondary_index+. For more information, see the documentation for
|
314
|
-
+find_global_each+ and +find_global+.
|
315
|
-
|
316
308
|
|
317
309
|
== Installation
|
318
310
|
|
@@ -335,8 +327,7 @@ to both the following locations in your project:
|
|
335
327
|
config/aws.yml.example
|
336
328
|
config/aws.yml
|
337
329
|
|
338
|
-
Enter your AWS credentials in the latter file.
|
339
|
-
will be a generator to copy these files for you, but for now you need to do it manually.
|
330
|
+
Enter your AWS credentials in the latter file.
|
340
331
|
|
341
332
|
|
342
333
|
== Running the specs
|
@@ -1,13 +1,15 @@
|
|
1
1
|
module OceanDynamo
|
2
2
|
module Associations
|
3
|
+
|
3
4
|
#
|
4
5
|
# This is the root class of all Associations.
|
5
6
|
# The class structure is exactly like in ActiveRecord:
|
6
7
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
8
|
+
# Associations
|
9
|
+
# Association
|
10
|
+
# CollectionAssociation
|
11
|
+
# HasAndBelongsToManyAssociation
|
12
|
+
# HasManyAssociation
|
11
13
|
#
|
12
14
|
# It should be noted, however, that the ActiveRecord documentation
|
13
15
|
# is misleading: belongs_to and has_one no longer are implemented using
|
@@ -151,7 +151,7 @@ module OceanDynamo
|
|
151
151
|
#
|
152
152
|
def assert_range_key_not_specified! # :nodoc:
|
153
153
|
raise RangeKeyMustNotBeSpecified,
|
154
|
-
"Tables with belongs_to relations may not specify
|
154
|
+
"Tables with belongs_to relations may not specify a range key" if table_range_key
|
155
155
|
end
|
156
156
|
|
157
157
|
|
@@ -1,15 +1,17 @@
|
|
1
1
|
module OceanDynamo
|
2
2
|
module Associations
|
3
|
+
|
3
4
|
#
|
4
5
|
# CollectionAssociation is an abstract class that provides common stuff to
|
5
6
|
# ease the implementation of association proxies that represent
|
6
7
|
# collections. See the class hierarchy in AssociationProxy.
|
7
8
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
9
|
+
# Associations
|
10
|
+
# Association
|
11
|
+
# CollectionAssociation:
|
12
|
+
# HasAndBelongsToManyAssociation => has_and_belongs_to_many
|
13
|
+
# HasManyAssociation => has_many
|
14
|
+
# HasManyThroughAssociation + ThroughAssociation => has_many :through
|
13
15
|
#
|
14
16
|
# CollectionAssociation class provides common methods to the collections
|
15
17
|
# defined by +has_and_belongs_to_many+, +has_many+ or +has_many+ with
|
@@ -19,9 +19,8 @@ module OceanDynamo
|
|
19
19
|
# <tt>@owner</tt>, the collection of its posts as <tt>@target</tt>, and
|
20
20
|
# the <tt>@reflection</tt> object represents a <tt>:has_many</tt> macro.
|
21
21
|
#
|
22
|
-
# This class delegates unknown methods to <tt>@target</tt>
|
23
|
-
#
|
24
|
-
# but through explicit proxy methods for each separate operation.
|
22
|
+
# This class delegates unknown methods to <tt>@target</tt> through explicit
|
23
|
+
# proxy methods for each separate operation.
|
25
24
|
#
|
26
25
|
# The <tt>@target</tt> object is not \loaded until needed. As it turns out,
|
27
26
|
# the key to this lazy loading scheme is <tt>to_ary</tt>.
|
@@ -19,11 +19,13 @@ module OceanDynamo
|
|
19
19
|
# Defines a +has_many+ relation to a +belongs_to+ class.
|
20
20
|
#
|
21
21
|
# The +dependent:+ keyword arg may be +:destroy+, +:delete+ or +:nullify+
|
22
|
-
# and have the same semantics as in ActiveRecord.
|
23
|
-
# the hash key is set to the string "NULL" rather than binary NULL, as
|
24
|
-
# DynamoDB doesn't permit storing empty fields.
|
22
|
+
# and have the same semantics as in ActiveRecord.
|
25
23
|
#
|
26
|
-
|
24
|
+
# Using +:nullify+ is a Bad Idea on DynamoDB, as it has to first read,
|
25
|
+
# then delete, and finally recreate each record. You should redesign your
|
26
|
+
# application to user either +:delete+ (the default) or +:destroy+ instead.
|
27
|
+
#
|
28
|
+
def has_many(children, dependent: :delete) # :children
|
27
29
|
children_attr = children.to_s.underscore # "children"
|
28
30
|
class_name = children_attr.classify # "Child"
|
29
31
|
define_class_if_not_defined(class_name)
|
@@ -176,6 +178,10 @@ module OceanDynamo
|
|
176
178
|
# into orphans. Note that we're not setting the key to NULL as this isn't possible
|
177
179
|
# in DynamoDB. Instead, we're using the literal string "NULL".
|
178
180
|
#
|
181
|
+
# Using +:nullify+ is a Bad Idea on DynamoDB, as it has to first read, then delete, and
|
182
|
+
# then recreate each record. You should redesign your application to user either
|
183
|
+
# +:delete? (the default) or +:destroy+ instead.
|
184
|
+
#
|
179
185
|
def nullify_children(child_class)
|
180
186
|
return if new_record?
|
181
187
|
opts = condition_options(child_class)
|
data/lib/ocean-dynamo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocean-dynamo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Bengtson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09
|
11
|
+
date: 2015-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -28,30 +28,30 @@ dependencies:
|
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '4'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '4'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rails
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '4
|
117
|
+
version: '4'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '4
|
124
|
+
version: '4'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: ocean-rails
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,18 +140,18 @@ description: "== OceanDynamo\n\nAs one important use case for OceanDynamo is to
|
|
140
140
|
the conversion of SQL\ndatabases to no-SQL DynamoDB databases, it is important that
|
141
141
|
the syntax and semantics\nof OceanDynamo are as close as possible to those of ActiveRecord.
|
142
142
|
This includes\ncallbacks, exceptions and method chaining semantics. OceanDynamo
|
143
|
-
follows this pattern \nclosely and is of course based on ActiveModel.\n\nThe attribute
|
143
|
+
follows this pattern \nclosely and is of course based on ActiveModel.\n\n\nThe attribute
|
144
144
|
and persistence layer of OceanDynamo is modeled on that of ActiveRecord:\nthere's
|
145
145
|
+save+, +save!+, +create+, +update+, +update!+, +update_attributes+, +find_each+,\n+destroy_all+,
|
146
146
|
+delete_all+, +read_attribute+, +write_attribute+ and all the other \nmethods you're
|
147
147
|
used to. The design goal is always to implement as much of the ActiveRecord\ninterface
|
148
148
|
as possible, without compromising scalability. This makes the task of switching
|
149
|
-
\nfrom SQL to no-SQL much easier.\n\nOceanDynamo uses only primary indices to
|
150
|
-
related table items and collections, \nwhich means it will scale without
|
151
|
-
is fully usable as an ActiveModel and can be used by Rails\ncontrollers.
|
152
|
-
to its structural similarity to ActiveRecord, OceanDynamo works \nwith FactoryGirl.\n\nSee
|
149
|
+
\nfrom SQL to no-SQL much easier.\n\n\nOceanDynamo uses only primary indices to
|
150
|
+
retrieve related table items and collections, \nwhich means it will scale without
|
151
|
+
limits.\n\n\nOceanDynamo is fully usable as an ActiveModel and can be used by Rails\ncontrollers.
|
152
|
+
Thanks to its structural similarity to ActiveRecord, OceanDynamo works \nwith FactoryGirl.\n\n\nSee
|
153
153
|
also Ocean, a Rails framework for creating highly scalable SOAs in the cloud, in
|
154
|
-
which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net"
|
154
|
+
which\nocean-dynamo is used as a central component: http://wiki.oceanframework.net\n"
|
155
155
|
email:
|
156
156
|
- peter@peterbengtson.com
|
157
157
|
executables: []
|