ocean-dynamo 1.2.4 → 1.3.0
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 +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: []
|