ocean-dynamo 0.4.4 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3dc795167d56cef7e557c8f233b0e6e2fe3a205a
4
- data.tar.gz: 4979ca24a5937658f00a325981dec200a81f0263
3
+ metadata.gz: f06f0f651adf9199dd190cedd203390528548a1f
4
+ data.tar.gz: 1082719f92e830ef6e60658b77048719cfaed6b1
5
5
  SHA512:
6
- metadata.gz: 4796a5bb3c5b216a96b10c9955ec6815ce676e869c7ec6367bb4534bb8f8f349535f96c77308dcaa18a49a786bdcfff631321787a01079bc356aa9f106a6d911
7
- data.tar.gz: 132101d4bb782d609c75e912a658f19ba423f455e2be2b2bad4d4a720ddc7f45aee1c1ded129bb6713026af0ada9703b14f0539804d4a7dede8d9eb4d478ae99
6
+ metadata.gz: 67d5231c8cef81f6b566c4e9a1f630c32dc510289a5fe3d27a05cb2a83a4bf5f31db1df13b16a6369e7482351dbbf87470d4bb8fa859710eae6290d050701ec5
7
+ data.tar.gz: b529ee10710b85465e3b82668268ed5c78226b83a2a3619f54c213492ebf4d8aa334b0344fefb960548db84e536dd92e8f614da51592a7849405e0f758402ccc
@@ -94,28 +94,37 @@ value will return the empty string, <tt>""</tt>.
94
94
 
95
95
  ==== Example
96
96
 
97
- The following example shows how to set up a +has_many+ / +belongs_to+ relation:
98
-
99
- class Child < OceanDynamo::Table; end
97
+ The following example shows how to set up +has_many+ / +belongs_to+ relations:
100
98
 
101
- class Parent < OceanDynamo::Table
99
+ class Forum < OceanDynamo::Table
102
100
  dynamo_schema do
103
- attribute :this
104
- attribute :that
105
- attribute :the_other
101
+ attribute :name
102
+ attribute :description
106
103
  end
107
- has_many :children, dependent: :destroy
104
+ has_many :topics, dependent: :destroy
108
105
  end
109
106
 
110
107
 
111
- class Child < OceanDynamo::Table
108
+ class Topic < OceanDynamo::Table
112
109
  dynamo_schema(:uuid) do
113
- attribute :foo
114
- attribute :bar
115
- attribute :baz
110
+ attribute :title
116
111
  end
117
- belongs_to :parent
112
+ belongs_to :forum
113
+ has_many :posts, dependent: :destroy
118
114
  end
115
+
116
+
117
+ class Post < OceanDynamo::Table
118
+ dynamo_schema(:uuid) do
119
+ attribute :body
120
+ end
121
+ belongs_to :topic, composite_key: true
122
+ end
123
+
124
+ The only non-standard aspect of the above is <tt>composite_key: true</tt>, which
125
+ is required as the Topic class itself has a +belongs_to+ relation and thus has
126
+ a composite key. This must be declared in the child class as it needs to know
127
+ how to retrieve its parent.
119
128
 
120
129
  ==== Restrictions
121
130
 
@@ -126,7 +135,6 @@ Restrictions for +belongs_to+ tables:
126
135
  * +belongs_to+ must be placed after the +dynamo_schema+ attribute block.
127
136
 
128
137
  Restrictions for +has_many+ tables:
129
- * The +has_many+ table may not have a range key.
130
138
  * +has_many+ must be placed after the +dynamo_schema+ attribute block.
131
139
 
132
140
  These restrictions allow OceanDynamo to implement the +has_many+ / +belongs_to+
@@ -162,10 +170,8 @@ controllers. OceanDynamo implements much of the infrastructure of ActiveRecord;
162
170
  for instance, +read_attribute+, +write_attribute+, and much of the control logic and
163
171
  internal organisation.
164
172
 
165
- * The +dependent:+ keyword arg may now be +:destroy+, +:delete+ or +:nullify+
166
- with the same semantics as in ActiveRecord. With +:nullify+, however,
167
- the hash key is set to the string "NULL" rather than binary NULL, as
168
- DynamoDB doesn't permit storing empty fields.
173
+ * +has_many+ can now be nested in multiple layers through the use of +:composite_key+
174
+ in +belongs_to+. See the documentation for +belongs_to+.
169
175
 
170
176
  === Future milestones
171
177
 
@@ -52,6 +52,11 @@ module OceanDynamo
52
52
  super
53
53
  end
54
54
 
55
+
56
+ def define_class_if_not_defined(class_name)
57
+ Object.const_set(class_name, Class.new(OceanDynamo::Table)) unless const_defined?(class_name)
58
+ end
59
+
55
60
  end
56
61
 
57
62
 
@@ -15,12 +15,46 @@ module OceanDynamo
15
15
  module ClassMethods
16
16
 
17
17
  #
18
- # Class macro to define the +belongs_to+ relation.
18
+ # Class macro to define the +belongs_to+ relation. For example:
19
19
  #
20
- def belongs_to(target) # :master, "master", Master
20
+ # class Forum < OceanDynamo::Table
21
+ # dynamo_schema do
22
+ # attribute :name
23
+ # attribute :description
24
+ # end
25
+ # has_many :topics, dependent: :destroy
26
+ # end
27
+ #
28
+ # class Topic < OceanDynamo::Table
29
+ # dynamo_schema(:uuid) do
30
+ # attribute :title
31
+ # end
32
+ # belongs_to :forum
33
+ # has_many :posts, dependent: :destroy
34
+ # end
35
+ #
36
+ # class Post < OceanDynamo::Table
37
+ # dynamo_schema(:uuid) do
38
+ # attribute :body
39
+ # end
40
+ # belongs_to :topic, composite_key: true
41
+ # end
42
+ #
43
+ # The only non-standard aspect of the above is <tt>composite_key: true</tt>,
44
+ # which is required as the Topic class itself has a +belongs_to+ relation and
45
+ # thus has a composite key. This must be declared in the child class as it
46
+ # needs to know how to retrieve its parent. If you were to add a Comment class
47
+ # to the above with a <tt>has_many/belongs_to</tt> relation to Post, the Comment
48
+ # class would also have a <tt>belongs_to :post, composite_key: true</tt> statement,
49
+ # since Post already has a composite key due to its +belongs_to+ relation to
50
+ # the Topic class.
51
+ #
52
+ def belongs_to(target, composite_key: false) # :master, "master", Master
21
53
  target_attr = target.to_s.underscore # "master"
22
54
  target_attr_id = "#{target_attr}_id" # "master_id"
23
- target_class = target_attr.camelize.constantize # Master
55
+ class_name = target_attr.classify # "Master"
56
+ define_class_if_not_defined(class_name)
57
+ target_class = class_name.constantize # Master
24
58
 
25
59
  assert_only_one_belongs_to!
26
60
 
@@ -47,7 +81,7 @@ module OceanDynamo
47
81
 
48
82
  # Define accessors for instances
49
83
  self.class_eval "def #{target_attr}
50
- @#{target_attr} ||= load_target_from_id('#{target_attr_id}')
84
+ @#{target_attr} ||= load_target_from_id('#{target_attr_id}', #{composite_key})
51
85
  end"
52
86
 
53
87
  self.class_eval "def #{target_attr_id}
@@ -55,7 +89,7 @@ module OceanDynamo
55
89
  end"
56
90
 
57
91
  self.class_eval "def #{target_attr}=(value)
58
- target, target_id = type_check_target(#{target_class}, value)
92
+ target, target_id = type_check_target(#{target_class}, value, #{composite_key})
59
93
  write_attribute('#{target_attr_id}', target_id)
60
94
  @#{target_attr} = target
61
95
  value
@@ -118,11 +152,6 @@ module OceanDynamo
118
152
  # Instance variables and methods
119
153
  #
120
154
  # ---------------------------------------------------------
121
- # def initialize(attrs={})
122
- # super
123
- # end
124
-
125
-
126
155
 
127
156
  #
128
157
  # This is run by #initialize and by #assign_attributes to set the
@@ -138,10 +167,11 @@ module OceanDynamo
138
167
  end
139
168
 
140
169
 
141
- def load_target_from_id(name) # :nodoc:
170
+ def load_target_from_id(name, composite_key) # :nodoc:
142
171
  v = read_attribute(name)
143
172
  return nil unless v
144
- fields[name][:target_class].find(v, consistent: true)
173
+ h, r = composite_key ? v.split(':') : v
174
+ fields[name][:target_class].find(h, r, consistent: true)
145
175
  end
146
176
 
147
177
 
@@ -152,10 +182,15 @@ module OceanDynamo
152
182
  end
153
183
 
154
184
 
155
- def type_check_target(target_class, value)
185
+ def type_check_target(target_class, value, composite_key)
156
186
  return nil unless value
157
- return [value, value.hash_key] if value.kind_of?(target_class)
158
- raise AssociationTypeMismatch, "can't save a #{value.class} in a #{target_class} foreign key"
187
+ if value.kind_of?(target_class)
188
+ foreign_key = value.hash_key
189
+ foreign_key += ':' + value.range_key if composite_key
190
+ return [value, foreign_key]
191
+ else
192
+ raise AssociationTypeMismatch, "can't save a #{value.class} in a #{target_class} foreign key"
193
+ end
159
194
  end
160
195
 
161
196
  end
@@ -16,16 +16,18 @@ module OceanDynamo
16
16
 
17
17
 
18
18
  #
19
- # Defines a has_many relation to a belongs_to class.
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
22
  # and have the same semantics as in ActiveRecord. With +:nullify+, however,
23
23
  # the hash key is set to the string "NULL" rather than binary NULL, as
24
24
  # DynamoDB doesn't permit storing empty fields.
25
25
  #
26
- def has_many(children, dependent: :nullify) # :children
27
- children_attr = children.to_s.underscore # "children"
28
- child_class = children_attr.singularize.camelize.constantize # Child
26
+ def has_many(children, dependent: :nullify) # :children
27
+ children_attr = children.to_s.underscore # "children"
28
+ class_name = children_attr.classify # "Child"
29
+ define_class_if_not_defined(class_name)
30
+ child_class = class_name.constantize # Child
29
31
  register_relation(child_class, :has_many)
30
32
 
31
33
  # Handle children= after create and update
@@ -1,3 +1,3 @@
1
1
  module OceanDynamo
2
- VERSION = "0.4.4"
2
+ VERSION = "0.5.0"
3
3
  end
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: 0.4.4
4
+ version: 0.5.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: 2013-09-30 00:00:00.000000000 Z
11
+ date: 2013-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk