ocean-dynamo 0.3.13 → 0.4.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 +3 -3
- data/lib/ocean-dynamo.rb +32 -3
- data/lib/ocean-dynamo/associations/associations.rb +58 -0
- data/lib/ocean-dynamo/associations/belongs_to.rb +93 -65
- data/lib/ocean-dynamo/associations/collection_proxy.rb +32 -32
- data/lib/ocean-dynamo/associations/has_many.rb +69 -0
- data/lib/ocean-dynamo/attributes.rb +22 -1
- data/lib/ocean-dynamo/basal.rb +32 -0
- data/lib/ocean-dynamo/class_variables.rb +4 -1
- data/lib/ocean-dynamo/exceptions.rb +5 -2
- data/lib/ocean-dynamo/persistence.rb +44 -37
- data/lib/ocean-dynamo/queries.rb +15 -9
- data/lib/ocean-dynamo/schema.rb +23 -18
- data/lib/ocean-dynamo/tables.rb +13 -9
- data/lib/ocean-dynamo/version.rb +1 -1
- metadata +4 -3
- data/lib/ocean-dynamo/base.rb +0 -38
- data/lib/ocean-dynamo/callbacks.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65a6bf63b42ff8ffecd0ea41b312b5657e62d5c9
|
4
|
+
data.tar.gz: 3055b4f29b1006c4fe80de69d97e31802653eb27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d365ff5096522676044fa6edbb3fd8e4c48de842636d820192e8674ce046de2f3af871d0b50236a837363daa24349819485003f09d32f06ab9d52d5c457745a
|
7
|
+
data.tar.gz: 997a24d91aa6a42f47dc38262200158120781ba74a9bd2355df304291d3796c3076d9dcd0710ce1cde96594abc8ea35cc617025f3034664b898e8d40ad0501a2
|
data/README.rdoc
CHANGED
@@ -34,7 +34,7 @@ which means it will scale without limits.
|
|
34
34
|
|
35
35
|
The following example shows the basic syntax for declaring a DynamoDB-based schema.
|
36
36
|
|
37
|
-
class AsyncJob < OceanDynamo::
|
37
|
+
class AsyncJob < OceanDynamo::Table
|
38
38
|
|
39
39
|
dynamo_schema(:uuid) do
|
40
40
|
attribute :credentials, :string
|
@@ -97,7 +97,7 @@ value will return the empty string, <tt>""</tt>.
|
|
97
97
|
|
98
98
|
The following example shows how to set up a +belongs_to+ relation:
|
99
99
|
|
100
|
-
class Parent < OceanDynamo::
|
100
|
+
class Parent < OceanDynamo::Table
|
101
101
|
dynamo_schema do
|
102
102
|
attribute :this
|
103
103
|
attribute :that
|
@@ -107,7 +107,7 @@ The following example shows how to set up a +belongs_to+ relation:
|
|
107
107
|
end
|
108
108
|
|
109
109
|
|
110
|
-
class Child < OceanDynamo::
|
110
|
+
class Child < OceanDynamo::Table
|
111
111
|
dynamo_schema(:uuid) do
|
112
112
|
attribute :foo
|
113
113
|
attribute :bar
|
data/lib/ocean-dynamo.rb
CHANGED
@@ -4,19 +4,48 @@ require "aws-sdk"
|
|
4
4
|
require "active_model"
|
5
5
|
require "active_support"
|
6
6
|
|
7
|
-
require "ocean-dynamo/base"
|
8
7
|
require "ocean-dynamo/exceptions"
|
9
8
|
require "ocean-dynamo/class_variables"
|
9
|
+
|
10
|
+
require "ocean-dynamo/basal"
|
10
11
|
require "ocean-dynamo/tables"
|
11
12
|
require "ocean-dynamo/schema"
|
12
13
|
require "ocean-dynamo/attributes"
|
13
|
-
require "ocean-dynamo/callbacks"
|
14
14
|
require "ocean-dynamo/persistence"
|
15
15
|
require "ocean-dynamo/queries"
|
16
|
-
|
16
|
+
require "ocean-dynamo/associations/associations"
|
17
17
|
require "ocean-dynamo/associations/belongs_to"
|
18
|
+
require "ocean-dynamo/associations/has_many"
|
18
19
|
|
19
20
|
|
20
21
|
module OceanDynamo
|
22
|
+
class Table
|
23
|
+
|
24
|
+
include ActiveModel::Model
|
25
|
+
include ActiveModel::Validations::Callbacks
|
26
|
+
|
27
|
+
define_model_callbacks :initialize, only: :after
|
28
|
+
define_model_callbacks :save
|
29
|
+
define_model_callbacks :create
|
30
|
+
define_model_callbacks :update
|
31
|
+
define_model_callbacks :destroy
|
32
|
+
define_model_callbacks :commit, only: :after
|
33
|
+
define_model_callbacks :touch
|
34
|
+
|
35
|
+
|
36
|
+
include Basal
|
37
|
+
|
38
|
+
extend Tables
|
39
|
+
extend Schema
|
40
|
+
|
41
|
+
include Attributes
|
42
|
+
include Persistence
|
43
|
+
extend Queries
|
44
|
+
|
45
|
+
include Associations
|
46
|
+
include BelongsTo
|
47
|
+
include HasMany
|
48
|
+
|
21
49
|
|
50
|
+
end
|
22
51
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module OceanDynamo
|
2
|
+
module Associations
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# ---------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Class methods
|
12
|
+
#
|
13
|
+
# ---------------------------------------------------------
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
#
|
20
|
+
def relates_to(klass)
|
21
|
+
relations[klass]
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
#
|
26
|
+
#
|
27
|
+
def register_relation(klass, value)
|
28
|
+
relations[klass] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
#
|
33
|
+
#
|
34
|
+
def clear_relations
|
35
|
+
self.relations = Hash.new
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def dynamo_schema(*)
|
40
|
+
clear_relations
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# ---------------------------------------------------------
|
48
|
+
#
|
49
|
+
# Instance variables and methods
|
50
|
+
#
|
51
|
+
# ---------------------------------------------------------
|
52
|
+
|
53
|
+
# def initialize(*)
|
54
|
+
# self.class.clear_relations
|
55
|
+
# end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -1,95 +1,123 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module BelongsTo
|
3
3
|
|
4
|
-
def self.
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
8
|
|
9
|
-
|
9
|
+
# ---------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Class methods
|
12
|
+
#
|
13
|
+
# ---------------------------------------------------------
|
10
14
|
|
11
|
-
|
12
|
-
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
#
|
20
|
+
def belongs_to(target) # :master, "master", Master
|
21
|
+
target_attr = target.to_s.underscore # "master"
|
22
|
+
target_attr_id = "#{target_attr}_id" # "master_id"
|
23
|
+
target_class = target_attr.camelize.constantize # Master
|
13
24
|
|
14
|
-
|
15
|
-
define_attribute_accessors(table_hash_key) # Define master_id, master_id=, master_id?
|
25
|
+
assert_only_one_belongs_to!
|
16
26
|
|
17
|
-
|
18
|
-
|
27
|
+
self.table_range_key = table_hash_key # The RANGE KEY is variable
|
28
|
+
self.table_hash_key = target_attr_id.to_sym # The HASH KEY is the parent UUID
|
19
29
|
|
20
|
-
|
21
|
-
|
22
|
-
define_attribute_accessors(table_range_key) # define uuid, uuid=, uuid?
|
30
|
+
attribute table_hash_key, :string # Define :master_id
|
31
|
+
define_attribute_accessors(table_hash_key) # Define master_id, master_id=, master_id?
|
23
32
|
|
33
|
+
# Make sure there always is a parent
|
34
|
+
validates(table_hash_key, presence: true) # Can't save without a parent_id
|
24
35
|
|
36
|
+
# Define the range attribute (our unique UUID)
|
37
|
+
attribute(table_range_key, :string, default: "") # Define :uuid
|
38
|
+
define_attribute_accessors(table_range_key) # define uuid, uuid=, uuid?
|
25
39
|
|
26
|
-
# Define the parent id attribute
|
27
|
-
attribute target_attr_id, :reference, default: nil, target_class: target_class,
|
28
|
-
association: :belongs_to
|
29
40
|
|
30
|
-
self.class_eval "def #{target_attr}
|
31
|
-
read_and_maybe_load_pointer('#{target_attr_id}')
|
32
|
-
end"
|
33
41
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
42
|
+
# Define the parent id attribute
|
43
|
+
attribute target_attr_id, :reference, default: nil, target_class: target_class,
|
44
|
+
association: :belongs_to
|
45
|
+
register_relation(target_class, :belongs_to)
|
38
46
|
|
39
|
-
self.class_eval "def #{target_attr_id}
|
40
|
-
get_pointer_id(@#{target_attr})
|
41
|
-
end"
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# TODO: "?" methods
|
48
|
-
end
|
48
|
+
# Define accessors for instances
|
49
|
+
self.class_eval "def #{target_attr}
|
50
|
+
read_and_maybe_load_pointer('#{target_attr_id}')
|
51
|
+
end"
|
49
52
|
|
53
|
+
self.class_eval "def #{target_attr}=(value)
|
54
|
+
write_attribute('#{target_attr_id}', value)
|
55
|
+
@#{target_attr} = value
|
56
|
+
end"
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
def self.has_belongs_to?
|
55
|
-
fields[table_hash_key]['association'] == :belongs_to
|
56
|
-
end
|
58
|
+
self.class_eval "def #{target_attr_id}
|
59
|
+
get_pointer_id(@#{target_attr})
|
60
|
+
end"
|
57
61
|
|
62
|
+
self.class_eval "def #{target_attr_id}=(value)
|
63
|
+
write_attribute('#{target_attr_id}', value)
|
64
|
+
@#{target_attr} = value
|
65
|
+
end"
|
66
|
+
# TODO: "?" methods
|
67
|
+
end
|
58
68
|
|
59
69
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
70
|
+
#
|
71
|
+
# Returns true if the class has a belongs_to association.
|
72
|
+
#
|
73
|
+
def has_belongs_to?
|
74
|
+
fields[table_hash_key]['association'] == :belongs_to
|
75
|
+
end
|
66
76
|
|
67
77
|
|
68
78
|
|
69
|
-
|
79
|
+
#
|
80
|
+
# Returns the class of the belongs_to association, or false if none.
|
81
|
+
#
|
82
|
+
def belongs_to_class
|
83
|
+
has_belongs_to? && fields[table_hash_key]['target_class']
|
84
|
+
end
|
70
85
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
86
|
+
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
#
|
91
|
+
# belongs_to can be specified only once in each model, since we use the range key to
|
92
|
+
# store its UUID and the hash key to store the UUID of the parent, as in
|
93
|
+
# ["parent_uuid", "child_uuid"]. This allows the parent to find all its children
|
94
|
+
# extremely efficiently by using only the primary index. It also allows the child
|
95
|
+
# to find its parent using only its own hash key. Presto: scalability without any
|
96
|
+
# secondary indices in the has_many/belongs_to association.
|
97
|
+
#
|
98
|
+
# Caveat: the parent must have a simple primary key, not a composite one. It *is*
|
99
|
+
# possible to use a composite key, but then the children must use scans to find
|
100
|
+
# their parents. We could conditionalise this, of course, so that the lookup
|
101
|
+
# strategy is transparent to the user.
|
102
|
+
#
|
103
|
+
def assert_only_one_belongs_to! # :nodoc:
|
104
|
+
if has_belongs_to?
|
105
|
+
raise OceanDynamo::AssociationMustBeUnique,
|
106
|
+
"#{self} already belongs_to #{belongs_to_class}"
|
107
|
+
end
|
108
|
+
false
|
88
109
|
end
|
89
|
-
false
|
90
110
|
end
|
91
111
|
|
92
112
|
|
113
|
+
# ---------------------------------------------------------
|
114
|
+
#
|
115
|
+
# Instance variables and methods
|
116
|
+
#
|
117
|
+
# ---------------------------------------------------------
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
93
121
|
#
|
94
122
|
# This is run by #initialize and by #assign_attributes to set the
|
95
123
|
# association variables (@master, for instance) and its associated attribute
|
@@ -15,7 +15,7 @@ module OceanDynamo
|
|
15
15
|
#
|
16
16
|
# For example, given
|
17
17
|
#
|
18
|
-
# class Blog < OceanDynamo::
|
18
|
+
# class Blog < OceanDynamo::Table
|
19
19
|
# has_many :posts
|
20
20
|
# end
|
21
21
|
#
|
@@ -66,7 +66,7 @@ module OceanDynamo
|
|
66
66
|
#
|
67
67
|
# *First:* Specify a subset of fields to be selected from the result set.
|
68
68
|
#
|
69
|
-
# class Person < OceanDynamo::
|
69
|
+
# class Person < OceanDynamo::Table
|
70
70
|
# has_many :pets
|
71
71
|
# end
|
72
72
|
#
|
@@ -121,10 +121,10 @@ module OceanDynamo
|
|
121
121
|
end
|
122
122
|
|
123
123
|
# Finds an object in the collection responding to the +id+. Uses the same
|
124
|
-
# rules as <tt>OceanDynamo::
|
124
|
+
# rules as <tt>OceanDynamo::Table.find</tt>. Returns <tt>OceanDynamo::RecordNotFound</tt>
|
125
125
|
# error if the object can not be found.
|
126
126
|
#
|
127
|
-
# class Person < OceanDynamo::
|
127
|
+
# class Person < OceanDynamo::Table
|
128
128
|
# has_many :pets
|
129
129
|
# end
|
130
130
|
#
|
@@ -154,7 +154,7 @@ module OceanDynamo
|
|
154
154
|
# If the collection is empty, the first form returns +nil+, and the second
|
155
155
|
# form returns an empty array.
|
156
156
|
#
|
157
|
-
# class Person < OceanDynamo::
|
157
|
+
# class Person < OceanDynamo::Table
|
158
158
|
# has_many :pets
|
159
159
|
# end
|
160
160
|
#
|
@@ -184,7 +184,7 @@ module OceanDynamo
|
|
184
184
|
# If the collection is empty, the first form returns +nil+, and the second
|
185
185
|
# form returns an empty array.
|
186
186
|
#
|
187
|
-
# class Person < OceanDynamo::
|
187
|
+
# class Person < OceanDynamo::Table
|
188
188
|
# has_many :pets
|
189
189
|
# end
|
190
190
|
#
|
@@ -215,7 +215,7 @@ module OceanDynamo
|
|
215
215
|
# You can pass an array of attributes hashes, this will return an array
|
216
216
|
# with the new objects.
|
217
217
|
#
|
218
|
-
# class Person < OceanDynamo::
|
218
|
+
# class Person < OceanDynamo::Table
|
219
219
|
# has_many :pets
|
220
220
|
# end
|
221
221
|
#
|
@@ -243,7 +243,7 @@ module OceanDynamo
|
|
243
243
|
# attributes, linked to this object and that has already been saved (if it
|
244
244
|
# passes the validations).
|
245
245
|
#
|
246
|
-
# class Person < OceanDynamo::
|
246
|
+
# class Person < OceanDynamo::Table
|
247
247
|
# has_many :pets
|
248
248
|
# end
|
249
249
|
#
|
@@ -271,7 +271,7 @@ module OceanDynamo
|
|
271
271
|
|
272
272
|
# Like +create+, except that if the record is invalid, raises an exception.
|
273
273
|
#
|
274
|
-
# class Person < OceanDynamo::
|
274
|
+
# class Person < OceanDynamo::Table
|
275
275
|
# has_many :pets
|
276
276
|
# end
|
277
277
|
#
|
@@ -290,7 +290,7 @@ module OceanDynamo
|
|
290
290
|
# inserts each record, +push+ and +concat+ behave identically. Returns +self+
|
291
291
|
# so method calls may be chained.
|
292
292
|
#
|
293
|
-
# class Person < OceanDynamo::
|
293
|
+
# class Person < OceanDynamo::Table
|
294
294
|
# pets :has_many
|
295
295
|
# end
|
296
296
|
#
|
@@ -316,7 +316,7 @@ module OceanDynamo
|
|
316
316
|
# Replaces this collection with +other_array+. This will perform a diff
|
317
317
|
# and delete/add only records that have changed.
|
318
318
|
#
|
319
|
-
# class Person < OceanDynamo::
|
319
|
+
# class Person < OceanDynamo::Table
|
320
320
|
# has_many :pets
|
321
321
|
# end
|
322
322
|
#
|
@@ -348,7 +348,7 @@ module OceanDynamo
|
|
348
348
|
# sets the foreign keys to <tt>NULL</tt>. For, +has_many+ <tt>:through</tt>,
|
349
349
|
# the default strategy is +delete_all+.
|
350
350
|
#
|
351
|
-
# class Person < OceanDynamo::
|
351
|
+
# class Person < OceanDynamo::Table
|
352
352
|
# has_many :pets # dependent: :nullify option by default
|
353
353
|
# end
|
354
354
|
#
|
@@ -381,7 +381,7 @@ module OceanDynamo
|
|
381
381
|
# are removed by calling their +destroy+ method. See +destroy+ for more
|
382
382
|
# information.
|
383
383
|
#
|
384
|
-
# class Person < OceanDynamo::
|
384
|
+
# class Person < OceanDynamo::Table
|
385
385
|
# has_many :pets, dependent: :destroy
|
386
386
|
# end
|
387
387
|
#
|
@@ -406,7 +406,7 @@ module OceanDynamo
|
|
406
406
|
# If it is set to <tt>:delete_all</tt>, all the objects are deleted
|
407
407
|
# *without* calling their +destroy+ method.
|
408
408
|
#
|
409
|
-
# class Person < OceanDynamo::
|
409
|
+
# class Person < OceanDynamo::Table
|
410
410
|
# has_many :pets, dependent: :delete_all
|
411
411
|
# end
|
412
412
|
#
|
@@ -435,7 +435,7 @@ module OceanDynamo
|
|
435
435
|
# This will _always_ remove the records ignoring the +:dependent+
|
436
436
|
# option.
|
437
437
|
#
|
438
|
-
# class Person < OceanDynamo::
|
438
|
+
# class Person < OceanDynamo::Table
|
439
439
|
# has_many :pets
|
440
440
|
# end
|
441
441
|
#
|
@@ -467,7 +467,7 @@ module OceanDynamo
|
|
467
467
|
# keys to <tt>NULL</tt>. For, +has_many+ <tt>:through</tt>, the default
|
468
468
|
# strategy is +delete_all+.
|
469
469
|
#
|
470
|
-
# class Person < OceanDynamo::
|
470
|
+
# class Person < OceanDynamo::Table
|
471
471
|
# has_many :pets # dependent: :nullify option by default
|
472
472
|
# end
|
473
473
|
#
|
@@ -495,7 +495,7 @@ module OceanDynamo
|
|
495
495
|
# If it is set to <tt>:destroy</tt> all the +records+ are removed by calling
|
496
496
|
# their +destroy+ method. See +destroy+ for more information.
|
497
497
|
#
|
498
|
-
# class Person < OceanDynamo::
|
498
|
+
# class Person < OceanDynamo::Table
|
499
499
|
# has_many :pets, dependent: :destroy
|
500
500
|
# end
|
501
501
|
#
|
@@ -523,7 +523,7 @@ module OceanDynamo
|
|
523
523
|
# If it is set to <tt>:delete_all</tt>, all the +records+ are deleted
|
524
524
|
# *without* calling their +destroy+ method.
|
525
525
|
#
|
526
|
-
# class Person < OceanDynamo::
|
526
|
+
# class Person < OceanDynamo::Table
|
527
527
|
# has_many :pets, dependent: :delete_all
|
528
528
|
# end
|
529
529
|
#
|
@@ -551,7 +551,7 @@ module OceanDynamo
|
|
551
551
|
# You can pass +Fixnum+ or +String+ values, it finds the records
|
552
552
|
# responding to the +id+ and executes delete on them.
|
553
553
|
#
|
554
|
-
# class Person < OceanDynamo::
|
554
|
+
# class Person < OceanDynamo::Table
|
555
555
|
# has_many :pets
|
556
556
|
# end
|
557
557
|
#
|
@@ -579,7 +579,7 @@ module OceanDynamo
|
|
579
579
|
# This method will _always_ remove record from the database ignoring
|
580
580
|
# the +:dependent+ option. Returns an array with the removed records.
|
581
581
|
#
|
582
|
-
# class Person < OceanDynamo::
|
582
|
+
# class Person < OceanDynamo::Table
|
583
583
|
# has_many :pets
|
584
584
|
# end
|
585
585
|
#
|
@@ -649,7 +649,7 @@ module OceanDynamo
|
|
649
649
|
|
650
650
|
# Specifies whether the records should be unique or not.
|
651
651
|
#
|
652
|
-
# class Person < OceanDynamo::
|
652
|
+
# class Person < OceanDynamo::Table
|
653
653
|
# has_many :pets
|
654
654
|
# end
|
655
655
|
#
|
@@ -668,7 +668,7 @@ module OceanDynamo
|
|
668
668
|
|
669
669
|
# Count all records using SQL.
|
670
670
|
#
|
671
|
-
# class Person < OceanDynamo::
|
671
|
+
# class Person < OceanDynamo::Table
|
672
672
|
# has_many :pets
|
673
673
|
# end
|
674
674
|
#
|
@@ -690,7 +690,7 @@ module OceanDynamo
|
|
690
690
|
# equivalent. If not and you are going to need the records anyway
|
691
691
|
# +length+ will take one less query. Otherwise +size+ is more efficient.
|
692
692
|
#
|
693
|
-
# class Person < OceanDynamo::
|
693
|
+
# class Person < OceanDynamo::Table
|
694
694
|
# has_many :pets
|
695
695
|
# end
|
696
696
|
#
|
@@ -716,7 +716,7 @@ module OceanDynamo
|
|
716
716
|
# equivalent. If not and you are going to need the records anyway this
|
717
717
|
# method will take one less query. Otherwise +size+ is more efficient.
|
718
718
|
#
|
719
|
-
# class Person < OceanDynamo::
|
719
|
+
# class Person < OceanDynamo::Table
|
720
720
|
# has_many :pets
|
721
721
|
# end
|
722
722
|
#
|
@@ -742,7 +742,7 @@ module OceanDynamo
|
|
742
742
|
# not already been loaded and you are going to fetch the records anyway it
|
743
743
|
# is better to check <tt>collection.length.zero?</tt>.
|
744
744
|
#
|
745
|
-
# class Person < OceanDynamo::
|
745
|
+
# class Person < OceanDynamo::Table
|
746
746
|
# has_many :pets
|
747
747
|
# end
|
748
748
|
#
|
@@ -759,7 +759,7 @@ module OceanDynamo
|
|
759
759
|
|
760
760
|
# Returns +true+ if the collection is not empty.
|
761
761
|
#
|
762
|
-
# class Person < OceanDynamo::
|
762
|
+
# class Person < OceanDynamo::Table
|
763
763
|
# has_many :pets
|
764
764
|
# end
|
765
765
|
#
|
@@ -793,7 +793,7 @@ module OceanDynamo
|
|
793
793
|
# Returns true if the collection has more than one record.
|
794
794
|
# Equivalent to <tt>collection.size > 1</tt>.
|
795
795
|
#
|
796
|
-
# class Person < OceanDynamo::
|
796
|
+
# class Person < OceanDynamo::Table
|
797
797
|
# has_many :pets
|
798
798
|
# end
|
799
799
|
#
|
@@ -830,7 +830,7 @@ module OceanDynamo
|
|
830
830
|
|
831
831
|
# Returns +true+ if the given object is present in the collection.
|
832
832
|
#
|
833
|
-
# class Person < OceanDynamo::
|
833
|
+
# class Person < OceanDynamo::Table
|
834
834
|
# has_many :pets
|
835
835
|
# end
|
836
836
|
#
|
@@ -869,7 +869,7 @@ module OceanDynamo
|
|
869
869
|
# to the corresponding element in the other array, otherwise returns
|
870
870
|
# +false+.
|
871
871
|
#
|
872
|
-
# class Person < OceanDynamo::
|
872
|
+
# class Person < OceanDynamo::Table
|
873
873
|
# has_many :pets
|
874
874
|
# end
|
875
875
|
#
|
@@ -895,7 +895,7 @@ module OceanDynamo
|
|
895
895
|
# Returns a new array of objects from the collection. If the collection
|
896
896
|
# hasn't been loaded, it fetches the records from the database.
|
897
897
|
#
|
898
|
-
# class Person < OceanDynamo::
|
898
|
+
# class Person < OceanDynamo::Table
|
899
899
|
# has_many :pets
|
900
900
|
# end
|
901
901
|
#
|
@@ -934,7 +934,7 @@ module OceanDynamo
|
|
934
934
|
# to the association's primary key. Returns +self+, so several appends may be
|
935
935
|
# chained together.
|
936
936
|
#
|
937
|
-
# class Person < OceanDynamo::
|
937
|
+
# class Person < OceanDynamo::Table
|
938
938
|
# has_many :pets
|
939
939
|
# end
|
940
940
|
#
|
@@ -971,7 +971,7 @@ module OceanDynamo
|
|
971
971
|
# Reloads the collection from the database. Returns +self+.
|
972
972
|
# Equivalent to <tt>collection(true)</tt>.
|
973
973
|
#
|
974
|
-
# class Person < OceanDynamo::
|
974
|
+
# class Person < OceanDynamo::Table
|
975
975
|
# has_many :pets
|
976
976
|
# end
|
977
977
|
#
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module OceanDynamo
|
2
|
+
module HasMany
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# ---------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Class methods
|
12
|
+
#
|
13
|
+
# ---------------------------------------------------------
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
#
|
20
|
+
def has_many(children) # :children
|
21
|
+
children_attr = children.to_s.underscore # "children"
|
22
|
+
child_class = children_attr.singularize.camelize.constantize # Child
|
23
|
+
register_relation(child_class, :has_many)
|
24
|
+
# Define accessors for instances
|
25
|
+
self.class_eval "def #{children_attr}; read_children(#{child_class}); end"
|
26
|
+
self.class_eval "def #{children_attr}=(value); write_children(#{child_class}, value); end"
|
27
|
+
# TODO: "?" method
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# ---------------------------------------------------------
|
34
|
+
#
|
35
|
+
# Instance variables and methods
|
36
|
+
#
|
37
|
+
# ---------------------------------------------------------
|
38
|
+
|
39
|
+
#
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def read_children(child_class)
|
43
|
+
if new_record?
|
44
|
+
nil
|
45
|
+
else
|
46
|
+
result = Array.new
|
47
|
+
_late_connect?
|
48
|
+
child_items = child_class.dynamo_items
|
49
|
+
child_items.query(hash_value: id, range_gte: "0") do |item_data|
|
50
|
+
result << child_class.new._setup_from_dynamo(item_data)
|
51
|
+
end
|
52
|
+
result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
#
|
58
|
+
#
|
59
|
+
def write_children(child_class, value)
|
60
|
+
return nil if value.blank?
|
61
|
+
raise AssociationTypeMismatch, "not an array or nil" if !value.is_a?(Array)
|
62
|
+
raise AssociationTypeMismatch, "an array element is not a #{child_class}" unless value.all? { |m| m.is_a?(child_class) }
|
63
|
+
# We now know that value is an array containing only members of the child_class
|
64
|
+
value.each(&:save!)
|
65
|
+
value
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -1,5 +1,26 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module Attributes
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# ---------------------------------------------------------
|
10
|
+
#
|
11
|
+
# Class methods
|
12
|
+
#
|
13
|
+
# ---------------------------------------------------------
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# ---------------------------------------------------------
|
20
|
+
#
|
21
|
+
# Instance variables and methods
|
22
|
+
#
|
23
|
+
# ---------------------------------------------------------
|
3
24
|
|
4
25
|
#
|
5
26
|
# The hash of attributes and their values. Keys are strings.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Basal
|
2
|
+
|
3
|
+
def ==(comparison_object)
|
4
|
+
super ||
|
5
|
+
comparison_object.instance_of?(self.class) &&
|
6
|
+
id.present? &&
|
7
|
+
comparison_object.id == id
|
8
|
+
end
|
9
|
+
alias :eql? :==
|
10
|
+
|
11
|
+
|
12
|
+
# Clone and freeze the attributes hash such that associations are still
|
13
|
+
# accessible, even on destroyed records, but cloned models will not be
|
14
|
+
# frozen.
|
15
|
+
def freeze
|
16
|
+
@attributes = @attributes.clone.freeze
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns +true+ if the attributes hash has been frozen.
|
21
|
+
def frozen?
|
22
|
+
@attributes.frozen?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Allows sort on objects
|
26
|
+
def <=>(other_object)
|
27
|
+
if other_object.is_a?(self.class)
|
28
|
+
self.to_key <=> other_object.to_key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
class
|
2
|
+
class Table
|
3
3
|
|
4
4
|
class_attribute :dynamo_client, instance_writer: false
|
5
5
|
self.dynamo_client = nil
|
@@ -49,5 +49,8 @@ module OceanDynamo
|
|
49
49
|
class_attribute :timestamp_attributes, instance_writer: false
|
50
50
|
self.timestamp_attributes = [:created_at, :updated_at]
|
51
51
|
|
52
|
+
class_attribute :relations, instance_writer: false
|
53
|
+
self.relations = nil
|
54
|
+
|
52
55
|
end
|
53
56
|
end
|
@@ -23,7 +23,7 @@ module OceanDynamo
|
|
23
23
|
def initialize(record) # :nodoc:
|
24
24
|
@record = record
|
25
25
|
errors = @record.errors.full_messages.join(", ")
|
26
|
-
super(
|
26
|
+
super(@record.errors.messages)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -38,7 +38,7 @@ module OceanDynamo
|
|
38
38
|
def initialize(record) # :nodoc:
|
39
39
|
@record = record
|
40
40
|
errors = @record.errors.full_messages.join(", ")
|
41
|
-
super(
|
41
|
+
super(@record.errors.messages)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
@@ -60,4 +60,7 @@ module OceanDynamo
|
|
60
60
|
class RangeKeyMustNotBeSpecified < BelongsToError; end
|
61
61
|
class HashKeyMayNotBeNamedId < BelongsToError; end
|
62
62
|
|
63
|
+
class HasManyError < DynamoError; end
|
64
|
+
|
65
|
+
|
63
66
|
end
|
@@ -1,5 +1,10 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module Persistence
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
3
8
|
|
4
9
|
# ---------------------------------------------------------
|
5
10
|
#
|
@@ -7,44 +12,55 @@ module OceanDynamo
|
|
7
12
|
#
|
8
13
|
# ---------------------------------------------------------
|
9
14
|
|
15
|
+
module ClassMethods
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
def create(attributes = nil, &block)
|
18
|
+
object = new(attributes)
|
19
|
+
yield(object) if block_given?
|
20
|
+
object.save
|
21
|
+
object
|
22
|
+
end
|
17
23
|
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
def create!(attributes = nil, &block)
|
26
|
+
object = new(attributes)
|
27
|
+
yield(object) if block_given?
|
28
|
+
object.save!
|
29
|
+
object
|
30
|
+
end
|
25
31
|
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
def delete(hash, range=nil)
|
34
|
+
item = dynamo_items[hash, range]
|
35
|
+
return false unless item.exists?
|
36
|
+
item.delete
|
37
|
+
true
|
38
|
+
end
|
33
39
|
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
def delete_all
|
42
|
+
dynamo_items.each() do |item|
|
43
|
+
item.delete
|
44
|
+
end
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def destroy_all
|
50
|
+
dynamo_items.select() do |item_data|
|
51
|
+
new._setup_from_dynamo(item_data).destroy
|
52
|
+
end
|
53
|
+
nil
|
38
54
|
end
|
39
|
-
nil
|
40
|
-
end
|
41
55
|
|
42
56
|
|
43
|
-
|
44
|
-
|
45
|
-
|
57
|
+
def _late_connect? # :nodoc:
|
58
|
+
return false if table_connected
|
59
|
+
return false unless table_connect_policy
|
60
|
+
establish_db_connection
|
61
|
+
true
|
46
62
|
end
|
47
|
-
|
63
|
+
|
48
64
|
end
|
49
65
|
|
50
66
|
|
@@ -176,7 +192,6 @@ module OceanDynamo
|
|
176
192
|
|
177
193
|
|
178
194
|
def reload(**keywords)
|
179
|
-
raise "HELLISHNESS" if id == range_key
|
180
195
|
new_instance = self.class.find(hash_key, range_key, **keywords)
|
181
196
|
assign_attributes(new_instance.attributes)
|
182
197
|
self
|
@@ -241,14 +256,6 @@ module OceanDynamo
|
|
241
256
|
|
242
257
|
protected
|
243
258
|
|
244
|
-
def self._late_connect? # :nodoc:
|
245
|
-
return false if table_connected
|
246
|
-
return false unless table_connect_policy
|
247
|
-
establish_db_connection
|
248
|
-
true
|
249
|
-
end
|
250
|
-
|
251
|
-
|
252
259
|
def _late_connect? # :nodoc:
|
253
260
|
self.class._late_connect?
|
254
261
|
end
|
data/lib/ocean-dynamo/queries.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module Queries
|
3
3
|
|
4
|
-
|
4
|
+
# ---------------------------------------------------------
|
5
|
+
#
|
6
|
+
# Class methods
|
7
|
+
#
|
8
|
+
# ---------------------------------------------------------
|
9
|
+
|
10
|
+
def find(hash, range=nil, consistent: false)
|
5
11
|
return hash.collect {|elem| find elem, range, consistent: consistent } if hash.is_a?(Array)
|
6
12
|
_late_connect?
|
7
|
-
hash = hash.id if hash.kind_of?(
|
13
|
+
hash = hash.id if hash.kind_of?(Table) # TODO: We have (innocuous) leakage, fix!
|
8
14
|
item = dynamo_items[hash, range]
|
9
15
|
unless item.exists?
|
10
16
|
raise RecordNotFound, "can't find a #{self} with primary key ['#{hash}', #{range.inspect}]"
|
@@ -13,14 +19,14 @@ module OceanDynamo
|
|
13
19
|
end
|
14
20
|
|
15
21
|
|
16
|
-
def
|
22
|
+
def find_by_key(*args)
|
17
23
|
find(*args)
|
18
24
|
rescue RecordNotFound
|
19
25
|
nil
|
20
26
|
end
|
21
27
|
|
22
28
|
|
23
|
-
def
|
29
|
+
def find_by_id(*args)
|
24
30
|
find_by_key(*args)
|
25
31
|
end
|
26
32
|
|
@@ -28,7 +34,7 @@ module OceanDynamo
|
|
28
34
|
#
|
29
35
|
# The number of records in the table.
|
30
36
|
#
|
31
|
-
def
|
37
|
+
def count(**options)
|
32
38
|
_late_connect?
|
33
39
|
dynamo_items.count(options)
|
34
40
|
end
|
@@ -37,7 +43,7 @@ module OceanDynamo
|
|
37
43
|
#
|
38
44
|
# Returns all records in the table.
|
39
45
|
#
|
40
|
-
def
|
46
|
+
def all(**options)
|
41
47
|
_late_connect?
|
42
48
|
result = []
|
43
49
|
dynamo_items.select(options) do |item_data|
|
@@ -54,7 +60,7 @@ module OceanDynamo
|
|
54
60
|
# In that case, batch processing methods allow you to work with the records in batches,
|
55
61
|
# thereby greatly reducing memory consumption.
|
56
62
|
#
|
57
|
-
def
|
63
|
+
def find_each(limit: nil, batch_size: 1000)
|
58
64
|
dynamo_items.select(limit: limit, batch_size: 1000) do |item_data|
|
59
65
|
yield new._setup_from_dynamo(item_data)
|
60
66
|
end
|
@@ -71,7 +77,7 @@ module OceanDynamo
|
|
71
77
|
# #
|
72
78
|
# # It’s not possible to set the order.
|
73
79
|
# #
|
74
|
-
# def
|
80
|
+
# def find_in_batches(start: nil, batch_size: 1000)
|
75
81
|
# []
|
76
82
|
# end
|
77
83
|
end
|
data/lib/ocean-dynamo/schema.rb
CHANGED
@@ -1,19 +1,24 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module Schema
|
3
3
|
|
4
|
+
# ---------------------------------------------------------
|
5
|
+
#
|
6
|
+
# Class methods
|
7
|
+
#
|
8
|
+
# ---------------------------------------------------------
|
4
9
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
def dynamo_schema(table_hash_key=:id,
|
11
|
+
table_range_key=nil,
|
12
|
+
table_name: compute_table_name,
|
13
|
+
table_name_prefix: nil,
|
14
|
+
table_name_suffix: nil,
|
15
|
+
read_capacity_units: 10,
|
16
|
+
write_capacity_units: 5,
|
17
|
+
connect: :late,
|
18
|
+
create: false,
|
19
|
+
locking: :lock_version,
|
20
|
+
timestamps: [:created_at, :updated_at],
|
21
|
+
&block)
|
17
22
|
# Set class vars
|
18
23
|
self.dynamo_client = nil
|
19
24
|
self.dynamo_table = nil
|
@@ -49,7 +54,7 @@ module OceanDynamo
|
|
49
54
|
end
|
50
55
|
|
51
56
|
|
52
|
-
def
|
57
|
+
def define_attribute_accessors(name)
|
53
58
|
name = name.to_s
|
54
59
|
self.class_eval "def #{name}; read_attribute('#{name}'); end"
|
55
60
|
self.class_eval "def #{name}=(value); write_attribute('#{name}', value); end"
|
@@ -57,17 +62,17 @@ module OceanDynamo
|
|
57
62
|
end
|
58
63
|
|
59
64
|
|
60
|
-
def
|
65
|
+
def compute_table_name
|
61
66
|
name.pluralize.underscore
|
62
67
|
end
|
63
68
|
|
64
69
|
|
65
|
-
def
|
70
|
+
def table_full_name
|
66
71
|
"#{table_name_prefix}#{table_name}#{table_name_suffix}"
|
67
72
|
end
|
68
73
|
|
69
74
|
|
70
|
-
def
|
75
|
+
def attribute(name, type=:string, default: nil, **extra)
|
71
76
|
raise DangerousAttributeError, "#{name} is defined by OceanDynamo" if self.dangerous_attributes.include?(name.to_s)
|
72
77
|
attr_accessor name
|
73
78
|
fields[name.to_s] = {type: type, default: default}.merge(extra)
|
@@ -76,7 +81,7 @@ module OceanDynamo
|
|
76
81
|
|
77
82
|
protected
|
78
83
|
|
79
|
-
def
|
84
|
+
def dangerous_attributes # :nodoc:
|
80
85
|
self.public_methods(false).collect do |sym|
|
81
86
|
str = sym.to_s
|
82
87
|
if str.end_with?("?", "=")
|
data/lib/ocean-dynamo/tables.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
module OceanDynamo
|
2
|
-
|
2
|
+
module Tables
|
3
3
|
|
4
|
-
|
4
|
+
# ---------------------------------------------------------
|
5
|
+
#
|
6
|
+
# Class methods
|
7
|
+
#
|
8
|
+
# ---------------------------------------------------------
|
9
|
+
|
10
|
+
def establish_db_connection
|
5
11
|
setup_dynamo
|
6
12
|
if dynamo_table.exists?
|
7
13
|
wait_until_table_is_active
|
@@ -14,7 +20,7 @@ module OceanDynamo
|
|
14
20
|
end
|
15
21
|
|
16
22
|
|
17
|
-
def
|
23
|
+
def setup_dynamo
|
18
24
|
#self.dynamo_client = AWS::DynamoDB::Client.new(:api_version => '2012-08-10')
|
19
25
|
self.dynamo_client ||= AWS::DynamoDB.new
|
20
26
|
self.dynamo_table = dynamo_client.tables[table_full_name]
|
@@ -22,7 +28,7 @@ module OceanDynamo
|
|
22
28
|
end
|
23
29
|
|
24
30
|
|
25
|
-
def
|
31
|
+
def wait_until_table_is_active
|
26
32
|
loop do
|
27
33
|
case dynamo_table.status
|
28
34
|
when :active
|
@@ -42,25 +48,23 @@ module OceanDynamo
|
|
42
48
|
end
|
43
49
|
|
44
50
|
|
45
|
-
def
|
51
|
+
def set_dynamo_table_keys
|
46
52
|
hash_key_type = fields[table_hash_key][:type]
|
47
53
|
hash_key_type = :string if hash_key_type == :reference
|
48
54
|
dynamo_table.hash_key = [table_hash_key, hash_key_type]
|
49
55
|
|
50
56
|
if table_range_key
|
51
57
|
range_key_type = fields[table_range_key][:type]
|
52
|
-
#range_key_type = :string if range_key_type == :reference
|
53
58
|
dynamo_table.range_key = [table_range_key, range_key_type]
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
57
62
|
|
58
|
-
def
|
63
|
+
def create_table
|
59
64
|
hash_key_type = fields[table_hash_key][:type]
|
60
65
|
hash_key_type = :string if hash_key_type == :reference
|
61
66
|
|
62
67
|
range_key_type = table_range_key && fields[table_range_key][:type]
|
63
|
-
#range_key_type = :string if range_key_type == :reference
|
64
68
|
|
65
69
|
self.dynamo_table = dynamo_client.tables.create(table_full_name,
|
66
70
|
table_read_capacity_units, table_write_capacity_units,
|
@@ -73,7 +77,7 @@ module OceanDynamo
|
|
73
77
|
end
|
74
78
|
|
75
79
|
|
76
|
-
def
|
80
|
+
def delete_table
|
77
81
|
return false unless dynamo_table.exists? && dynamo_table.status == :active
|
78
82
|
dynamo_table.delete
|
79
83
|
true
|
data/lib/ocean-dynamo/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ocean-dynamo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Bengtson
|
@@ -160,11 +160,12 @@ extensions: []
|
|
160
160
|
extra_rdoc_files: []
|
161
161
|
files:
|
162
162
|
- config/routes.rb
|
163
|
+
- lib/ocean-dynamo/associations/associations.rb
|
163
164
|
- lib/ocean-dynamo/associations/belongs_to.rb
|
164
165
|
- lib/ocean-dynamo/associations/collection_proxy.rb
|
166
|
+
- lib/ocean-dynamo/associations/has_many.rb
|
165
167
|
- lib/ocean-dynamo/attributes.rb
|
166
|
-
- lib/ocean-dynamo/
|
167
|
-
- lib/ocean-dynamo/callbacks.rb
|
168
|
+
- lib/ocean-dynamo/basal.rb
|
168
169
|
- lib/ocean-dynamo/class_variables.rb
|
169
170
|
- lib/ocean-dynamo/engine.rb
|
170
171
|
- lib/ocean-dynamo/exceptions.rb
|
data/lib/ocean-dynamo/base.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
module OceanDynamo
|
2
|
-
class Base
|
3
|
-
|
4
|
-
include ActiveModel::Model
|
5
|
-
include ActiveModel::Validations::Callbacks
|
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
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module OceanDynamo
|
2
|
-
class Base
|
3
|
-
|
4
|
-
include ActiveModel::Validations::Callbacks
|
5
|
-
|
6
|
-
define_model_callbacks :initialize, only: :after
|
7
|
-
define_model_callbacks :save
|
8
|
-
define_model_callbacks :create
|
9
|
-
define_model_callbacks :update
|
10
|
-
define_model_callbacks :destroy
|
11
|
-
define_model_callbacks :commit, only: :after
|
12
|
-
define_model_callbacks :touch
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|