isomorfeus-data 1.0.0.zeta10 → 1.0.0.zeta11

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.
@@ -18,53 +18,103 @@ module LucidData
18
18
  @node_collections ||= {}
19
19
  end
20
20
 
21
- def nodes(access_name, collection_class = nil)
22
- node_collections[access_name] = collection_class
21
+ def nodes(access_name, validate_hash = {})
22
+ node_collections[access_name] = validate_hash
23
23
 
24
24
  define_method(access_name) do
25
25
  node_collections[access_name]
26
26
  end
27
27
 
28
28
  define_method("#{access_name}=") do |collection|
29
+ _validate_node_collection(access_name, collection)
29
30
  @_changed = true
30
31
  node_collections[access_name] = collection
31
32
  node_collections[access_name].graph = self
32
33
  node_collections[access_name]
33
34
  end
34
35
 
35
- if collection_class
36
- singular_access_name = access_name.to_s.singularize
37
- define_singleton_method("valid_#{singular_access_name}?") do |node|
38
- collection_class.valid_node?(node)
39
- end
36
+ define_singleton_method("valid_#{access_name}?") do |collection|
37
+ _validate_node_collection(access_name, collection)
38
+ rescue
39
+ false
40
40
  end
41
41
  end
42
42
  alias documents nodes
43
43
  alias vertices nodes
44
44
  alias vertexes nodes
45
45
 
46
- def edges(access_name, collection_class = nil)
47
- edge_collections[access_name] = collection_class
46
+ def _validate_nodes(nodes_hash_or_array)
47
+ if nodes_hash_or_array.class == ::Hash
48
+ nodes_hash_or_array.each do |access_name, collection|
49
+ _validate_node_collection(access_name, collection)
50
+ end
51
+ else
52
+ _validate_node_collection(:nodes, nodes_hash_or_array)
53
+ end
54
+ end
55
+
56
+ def _validate_node_collection(access_name, collection)
57
+ unless node_collections.key?(access_name) || access_name == :nodes
58
+ raise "#{self.name}: No such node collection declared: '#{access_name}'!"
59
+ end
60
+ Isomorfeus::Data::ElementValidator.new(self.name, collection, node_collections[access_name]).validate! if node_collections[access_name]
61
+ end
62
+
63
+ def edges(access_name, validate_hash = {})
64
+ edge_collections[access_name] = validate_hash
48
65
 
49
66
  define_method(access_name) do
50
67
  edge_collections[access_name]
51
68
  end
52
69
 
53
70
  define_method("#{access_name}=") do |collection|
71
+ _validate_edge_collection(access_name, collection)
54
72
  @_changed = true
55
73
  edge_collections[access_name] = collection
56
74
  edge_collections[access_name].graph = self
57
75
  edge_collections[access_name]
58
76
  end
59
77
 
60
- if collection_class
61
- singular_access_name = access_name.to_s.singularize
62
- define_singleton_method("valid_#{singular_access_name}?") do |edge|
63
- collection_class.valid_edge?(edge)
64
- end
78
+ define_singleton_method("valid_#{access_name}?") do |collection|
79
+ _validate_edge_collection(access_name, collection)
80
+ rescue
81
+ false
65
82
  end
66
83
  end
67
84
  alias links edges
85
+
86
+ def _validate_edges(edges_hash_or_array)
87
+ if edges_hash_or_array.class == ::Hash
88
+ edges_hash_or_array.each do |access_name, collection|
89
+ _validate_edge_collection(access_name, collection)
90
+ end
91
+ else
92
+ _validate_edge_collection(:edges, edges_hash_or_array)
93
+ end
94
+ end
95
+
96
+ def _validate_edge_collection(access_name, collection)
97
+ unless edge_collections.key?(access_name) || access_name == :edges
98
+ raise "#{self.name}: No such edge collection declared: '#{access_name}'!"
99
+ end
100
+ Isomorfeus::Data::ElementValidator.new(self.name, collection, edge_collections[access_name]).validate! if edge_collections[access_name]
101
+ end
102
+ end
103
+
104
+ def _validate_edges(edges_hash_or_array)
105
+ self.class._validate_edges(edges_hash_or_array)
106
+ end
107
+
108
+ def _validate_edge_collection(access_name, collection)
109
+ self.class._validate_edge_collection(access_name, collection)
110
+ end
111
+
112
+ def _validate_nodes(nodes_hash_or_array)
113
+ self.class._validate_nodes(nodes_hash_or_array)
114
+ end
115
+
116
+ def _validate_node_collection(access_name, collection)
117
+ self.class._validate_node_collection(access_name, collection)
68
118
  end
69
119
 
70
120
  def method_missing(method_name, *args, &block)
@@ -200,7 +250,7 @@ module LucidData
200
250
  loaded = loaded?
201
251
 
202
252
  if attributes
203
- attributes.each { |a,v| _validate_attribute(a, v) }
253
+ _validate_attributes(attributes)
204
254
  if loaded
205
255
  raw_attributes = Redux.fetch_by_path(*@_store_path)
206
256
  if `raw_attributes === null`
@@ -219,6 +269,7 @@ module LucidData
219
269
  @_node_collections = {}
220
270
  nodes = nodes || documents || vertices || vertexes
221
271
  if nodes && loaded
272
+ _validate_nodes(nodes)
222
273
  if nodes.class == ::Hash
223
274
  self.class.node_collections.each_key do |access_name|
224
275
  if nodes.key?(access_name)
@@ -249,6 +300,7 @@ module LucidData
249
300
  @_edge_collections = {}
250
301
  edges = edges || links
251
302
  if edges && loaded
303
+ _validate_edges(edges)
252
304
  if edges.class == ::Hash
253
305
  self.class.edge_collections.each_key do |access_name|
254
306
  if edges.key?(access_name)
@@ -329,34 +381,54 @@ module LucidData
329
381
 
330
382
  base.instance_exec do
331
383
  def load(key:, pub_sub_client: nil, current_user: nil)
332
- data = instance_exec(key: key, &@_load_block)
333
- revision = nil
334
- revision = data.delete(:revision) if data.key?(:revision)
384
+ data = instance_exec(key: key, pub_sub_client: pub_sub_client, current_user: current_user, &@_load_block)
385
+ revision = data.delete(:revision)
335
386
  nodes = data.delete(:nodes)
336
387
  edges = data.delete(:edges)
337
388
  attributes = data.delete(:attributes)
338
389
  self.new(key: key, revision: revision, edges: edges, nodes: nodes, attributes: attributes)
339
390
  end
391
+
392
+ def save(key:, revision: nil, attributes: nil, edges: nil, links: nil, nodes: nil, documents: nil, vertices: nil, vertexes: nil,
393
+ pub_sub_client: nil, current_user: nil)
394
+ attributes = {} unless attributes
395
+ val_edges = edges || links
396
+ val_nodes = documents || nodes || vertexes || vertices
397
+ _validate_attributes(attributes) if attributes.any?
398
+ _validate_edges(val_edges)
399
+ _validate_nodes(val_nodes)
400
+ data = instance_exec(key: key, revision: revision, parts: parts, attributes: attributes,
401
+ pub_sub_client: pub_sub_client, current_user: current_user, &@_save_block)
402
+ revision = data.delete(:revision)
403
+ attributes = data.delete(:attributes)
404
+ documents = data.delete(:documents)
405
+ vertexes = data.delete(:vertexes)
406
+ vertices = data.delete(:vertices)
407
+ nodes = data.delete(:nodes)
408
+ edges = data.delete(:edges)
409
+ links = data.delete(:links)
410
+ self.new(key: key, revision: revision, attributes: attributes, edges: edges, links: links, nodes: nodes, documents: documents,
411
+ vertices: vertices, vertexes: vertexes, pub_sub_client: nil, current_user: nil)
412
+ end
340
413
  end
341
414
 
342
- def initialize(key:, revision: nil, attributes: nil, edges: nil, links: nil, nodes: nil, documents: nil, vertices: nil, vertexes: nil, composition: nil)
415
+ def initialize(key:, revision: nil, attributes: nil, edges: nil, links: nil, nodes: nil, documents: nil, vertices: nil, vertexes: nil,
416
+ composition: nil)
343
417
  @key = key.to_s
344
418
  @class_name = self.class.name
345
419
  @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
346
420
  @_revision = revision
347
421
  @_changed = false
348
422
  @_composition = composition
349
- @_validate_attributes = self.class.attribute_conditions.any?
350
423
  attributes = {} unless attributes
351
- if @_validate_attributes
352
- attributes.each { |a,v| _validate_attribute(a, v) }
353
- end
424
+ _validate_attributes(attributes) if attributes.any?
354
425
  @_raw_attributes = attributes
355
426
 
356
427
  # nodes
357
428
  @_node_collections = {}
358
429
  nodes = nodes || documents || vertices || vertexes
359
430
  if nodes.class == ::Hash
431
+ _validate_nodes(nodes)
360
432
  self.class.node_collections.each_key do |access_name|
361
433
  if nodes.key?(access_name)
362
434
  @_node_collections[access_name] = nodes[access_name]
@@ -364,6 +436,7 @@ module LucidData
364
436
  end
365
437
  end
366
438
  else
439
+ _validate_nodes(nodes) if nodes
367
440
  @_node_collections[:nodes] = nodes ? nodes : []
368
441
  @_node_collections[:nodes].graph = self if @_node_collections[:nodes].respond_to?(:graph=)
369
442
  end
@@ -372,6 +445,7 @@ module LucidData
372
445
  @_edge_collections = {}
373
446
  edges = edges || links
374
447
  if edges.class == ::Hash
448
+ _validate_edges(edges)
375
449
  self.class.edge_collections.each_key do |access_name|
376
450
  if edges.key?(access_name)
377
451
  @_edge_collections[access_name] = edges[access_name]
@@ -379,6 +453,7 @@ module LucidData
379
453
  end
380
454
  end
381
455
  else
456
+ _validate_edges(edges) if edges
382
457
  @_edge_collections[:edges] = edges ? edges : []
383
458
  @_edge_collections[:edges].graph = self if @_edge_collections[:edges].respond_to?(:graph=)
384
459
  end
@@ -4,6 +4,7 @@ module LucidData
4
4
  def self.included(base)
5
5
  base.include(Enumerable)
6
6
  base.extend(LucidPropDeclaration::Mixin)
7
+ base.include(Isomorfeus::Data::AttributeSupport)
7
8
  base.extend(Isomorfeus::Data::GenericClassApi)
8
9
  base.include(Isomorfeus::Data::GenericInstanceApi)
9
10
 
@@ -11,16 +12,25 @@ module LucidData
11
12
  attr_accessor :default_proc
12
13
 
13
14
  base.instance_exec do
14
- def attribute_conditions
15
- @attribute_conditions ||= {}
16
- end
17
-
18
15
  def valid_attribute?(attr_name, attr_value)
19
- return true unless @attribute_conditions
16
+ return true unless attribute_conditions.any?
20
17
  Isomorfeus::Props::Validator.new(self.name, attr_name, attr_value, attribute_conditions[attr_name]).validate!
21
18
  rescue
22
19
  false
23
20
  end
21
+
22
+ def _relaxed_validate_attribute(attr_name, attr_val)
23
+ Isomorfeus::Props::Validator.new(@class_name, attr_name, attr_val, attribute_conditions[attr_name]).validate!
24
+ end
25
+
26
+ def _relaxed_validate_attributes(attrs)
27
+ attribute_conditions.each_key do |attr|
28
+ if attribute_conditions[attr].key?(:required) && attribute_conditions[attr][:required] && !attrs.key?(attr)
29
+ raise "Required attribute #{attr} not given!"
30
+ end
31
+ end
32
+ attrs.each { |attr, val| _relaxed_validate_attribute(attr, val) } if attribute_conditions.any?
33
+ end
24
34
  end
25
35
 
26
36
  def composition
@@ -42,8 +52,12 @@ module LucidData
42
52
  { @class_name => { @key => hash }}
43
53
  end
44
54
 
45
- def _validate_attribute(attr_name, attr_val)
46
- Isomorfeus::Props::Validator.new(@class_name, attr_name, attr_val, self.class.attribute_conditions[attr_name]).validate!
55
+ def _relaxed_validate_attribute(attr_name, attr_val)
56
+ self.class._relaxed_validate_attribute(attr_name, attr_val)
57
+ end
58
+
59
+ def _relaxed_validate_attributes(attrs)
60
+ self.class._relaxed_validate_attributes(attrs)
47
61
  end
48
62
 
49
63
  if RUBY_ENGINE == 'opal'
@@ -63,7 +77,7 @@ module LucidData
63
77
  end
64
78
 
65
79
  define_method("#{name}=") do |val|
66
- _validate_attribute(name, val) if @_validate_attributes
80
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
67
81
  @_changed_attributes[name] = val
68
82
  end
69
83
  end
@@ -82,9 +96,7 @@ module LucidData
82
96
  @_composition = composition
83
97
  @_validate_attributes = self.class.attribute_conditions.any?
84
98
  attributes = {} unless attributes
85
- if @_validate_attributes
86
- attributes.each { |a,v| _validate_attribute(a, v) }
87
- end
99
+ _relaxed_validate_attributes(attributes) if @_validate_attributes
88
100
  raw_attributes = Redux.fetch_by_path(*@_store_path)
89
101
  if `raw_attributes === null`
90
102
  @_changed_attributes = !attributes ? {} : attributes
@@ -129,7 +141,7 @@ module LucidData
129
141
  end
130
142
 
131
143
  def []=(name, val)
132
- _validate_attribute(name, val) if @_validate_attributes
144
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
133
145
  changed!
134
146
  @_changed_attributes[name] = val
135
147
  end
@@ -161,7 +173,7 @@ module LucidData
161
173
  def method_missing(method_name, *args, &block)
162
174
  if method_name.end_with?('=')
163
175
  val = args[0]
164
- _validate_attribute(method_name, val) if @_validate_attributes
176
+ _relaxed_validate_attribute(method_name, val) if @_validate_attributes
165
177
  changed!
166
178
  @_changed_attributes[method_name] = val
167
179
  elsif args.size == 0 && hash.key?(method_name)
@@ -222,7 +234,7 @@ module LucidData
222
234
  end
223
235
 
224
236
  def store(name, val)
225
- _validate_attribute(name, val) if @_validate_attributes
237
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
226
238
  @_changed_attributes[name] = val
227
239
  changed!
228
240
  val
@@ -265,16 +277,25 @@ module LucidData
265
277
  end
266
278
 
267
279
  define_method("#{name}=") do |val|
268
- _validate_attribute(name, val) if @_validate_attributes
280
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
269
281
  changed!
270
282
  @_raw_attributes[name] = val
271
283
  end
272
284
  end
273
285
 
274
286
  def load(key:, pub_sub_client: nil, current_user: nil)
275
- data = instance_exec(key: key, &@_load_block)
276
- revision = nil
277
- revision = data.delete(:revision) if data.key?(:revision)
287
+ data = instance_exec(key: key, pub_sub_client: pub_sub_client, current_user: current_user, &@_load_block)
288
+ revision = data.delete(:revision)
289
+ attributes = data.delete(:attributes)
290
+ self.new(key: key, revision: revision, attributes: attributes)
291
+ end
292
+
293
+ def save(key:, revision: nil, attributes: nil, pub_sub_client: nil, current_user: nil)
294
+ attributes = {} unless attributes
295
+ _relaxed_validate_attributes(attributes)
296
+ data = instance_exec(key: key, revision: revision, attributes: attributes,
297
+ pub_sub_client: pub_sub_client, current_user: current_user, &@_save_block)
298
+ revision = data.delete(:revision)
278
299
  attributes = data.delete(:attributes)
279
300
  self.new(key: key, revision: revision, attributes: attributes)
280
301
  end
@@ -289,9 +310,7 @@ module LucidData
289
310
  @_changed = false
290
311
  @_validate_attributes = self.class.attribute_conditions.any?
291
312
  attributes = {} unless attributes
292
- if @_validate_attributes
293
- attributes.each { |a,v| _validate_attribute(a, v) }
294
- end
313
+ _relaxed_validate_attributes(attributes) if @_validate_attributes
295
314
  @_raw_attributes = attributes
296
315
  end
297
316
 
@@ -308,7 +327,7 @@ module LucidData
308
327
  end
309
328
 
310
329
  def []=(name, val)
311
- _validate_attribute(name, val) if @_validate_attributes
330
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
312
331
  changed!
313
332
  @_raw_attributes[name] = val
314
333
  end
@@ -341,7 +360,7 @@ module LucidData
341
360
  def method_missing(method_name, *args, &block)
342
361
  if method_name.end_with?('=')
343
362
  val = args[0]
344
- _validate_attribute(name, val) if @_validate_attributes
363
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
345
364
  changed!
346
365
  @_raw_attributes[name] = val
347
366
  elsif args.size == 0 && @_raw_attributes.key?(method_name)
@@ -379,7 +398,7 @@ module LucidData
379
398
  end
380
399
 
381
400
  def store(name, val)
382
- _validate_attribute(name, val) if @_validate_attributes
401
+ _relaxed_validate_attribute(name, val) if @_validate_attributes
383
402
  changed!
384
403
  @_raw_attributes[name] = val
385
404
  end
@@ -63,7 +63,7 @@ module LucidData
63
63
  @_changed = false
64
64
  loaded = loaded?
65
65
  if attributes
66
- attributes.each { |a,v| _validate_attribute(a, v) }
66
+ _validate_attributes(attributes)
67
67
  if loaded
68
68
  raw_attributes = Redux.fetch_by_path(*@_store_path)
69
69
  if `raw_attributes === null`
@@ -146,11 +146,19 @@ module LucidData
146
146
 
147
147
  base.instance_exec do
148
148
  def load(key:, pub_sub_client: nil, current_user: nil)
149
- data = instance_exec(key: key, &@_load_block)
150
- revision = nil
151
- revision = data.delete(:revision) if data.key?(:revision)
152
- data.delete(:_key)
153
- attributes = data.key?(:attributes) ? data.delete(:attributes) : data
149
+ data = instance_exec(key: key, pub_sub_client: pub_sub_client, current_user: current_user, &@_load_block)
150
+ revision = data.delete(:revision)
151
+ attributes = data.delete(:attributes)
152
+ self.new(key: key, revision: revision, attributes: attributes)
153
+ end
154
+
155
+ def save(key:, revision: nil, attributes: nil, pub_sub_client: nil, current_user: nil)
156
+ attributes = {} unless attributes
157
+ _validate_attributes(attributes)
158
+ data = instance_exec(key: key, revision: revision, attributes: attributes,
159
+ pub_sub_client: pub_sub_client, current_user: current_user, &@_save_block)
160
+ revision = data.delete(:revision)
161
+ attributes = data.delete(:attributes)
154
162
  self.new(key: key, revision: revision, attributes: attributes)
155
163
  end
156
164
  end
@@ -163,11 +171,8 @@ module LucidData
163
171
  @_collection = collection
164
172
  @_composition = composition
165
173
  @_changed = false
166
- @_validate_attributes = self.class.attribute_conditions.any?
167
174
  attributes = {} unless attributes
168
- if @_validate_attributes
169
- attributes.each { |a,v| _validate_attribute(a, v) }
170
- end
175
+ _validate_attributes(attributes) if attributes
171
176
  @_raw_attributes = attributes
172
177
  end
173
178
 
@@ -0,0 +1,93 @@
1
+ module LucidData
2
+ class QueryResult
3
+ attr_reader :key
4
+
5
+ def to_sid
6
+ [@class_name, @key]
7
+ end
8
+
9
+ if RUBY_ENGINE == 'opal'
10
+ def initialize(key: nil, result_set: {})
11
+ @class_name = 'LucidData::QueryResult'
12
+ @key = key ? key.to_s : self.object_id.to_s
13
+ @result_set = result_set
14
+ end
15
+
16
+ def _load_from_store!
17
+ @result_set = nil
18
+ end
19
+
20
+ def loaded?
21
+ Redux.fetch_by_path([:data_state, @class_name, @key]) ? true : false
22
+ end
23
+
24
+ def key?(k)
25
+ if @result_set.any?
26
+ @result_set.key?(k)
27
+ else
28
+ stored_results = Redux.fetch_by_path([:data_state, @class_name, @key])
29
+ `Object.hasOwnProperty(stored_results, k)`
30
+ end
31
+ end
32
+ alias has_key? key?
33
+
34
+ def result_set=(r)
35
+ @result_set = r
36
+ end
37
+
38
+ def method_missing(accessor_name, *args, &block)
39
+ raise "#{@class_name}: no such thing '#{accessor_name}‘in the results!" unless @result_set.key?(accessor_name)
40
+ sid = if @result_set.any?
41
+ @result_set[accessor_name]
42
+ else
43
+ stored_results = Redux.fetch_by_path([:data_state, @class_name, @key])
44
+ stored_results.JS[accessor_name]
45
+ end
46
+ Isomorfeus.instance_from_sid(sid)
47
+ end
48
+ else
49
+ def initialize(key: nil, result_set: {})
50
+ @class_name = 'LucidData::QueryResult'
51
+ @key = key ? key.to_s : self.object_id.to_s
52
+ @result_set = result_set
53
+ end
54
+
55
+ def loaded?
56
+ @result_set.any?
57
+ end
58
+
59
+ def key?(k)
60
+ @result_set.key?(k)
61
+ end
62
+ alias has_key? key?
63
+
64
+ def result_set=(r)
65
+ @result_set = r
66
+ end
67
+
68
+ def method_missing(accessor_name, *args, &block)
69
+ raise "#{@class_name}: no such thing '#{accessor_name}‘in the results!" unless @result_set.key?(accessor_name)
70
+ @result_set[accessor_name]
71
+ end
72
+
73
+ def to_transport
74
+ sids_hash = {}
75
+ @result_set.each do |key, value|
76
+ sids_hash[key] = value.to_sid
77
+ end
78
+ { @class_name => { @key => sids_hash }}
79
+ end
80
+
81
+ def included_items_to_transport
82
+ data_hash = {}
83
+ @result_set.each_value do |value|
84
+ data_hash.deep_merge!(value.to_transport)
85
+ if value.respond_to?(:included_items_to_transport)
86
+ data_hash.deep_merge!(value.included_items_to_transport)
87
+ end
88
+ end
89
+ data_hash
90
+ end
91
+ end
92
+ end
93
+ end