isomorfeus-data 1.0.0.zeta25 → 2.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +47 -21
- data/README.md +38 -46
- data/lib/isomorfeus/data/attribute_support.rb +176 -176
- data/lib/isomorfeus/data/config.rb +79 -110
- data/lib/isomorfeus/data/element_validator.rb +147 -147
- data/lib/isomorfeus/data/ferret_accelerator.rb +66 -0
- data/lib/isomorfeus/data/field_support.rb +110 -0
- data/lib/isomorfeus/data/generic_class_api.rb +136 -116
- data/lib/isomorfeus/data/generic_instance_api.rb +150 -145
- data/lib/isomorfeus/data/hamster_accelerator.rb +87 -0
- data/lib/isomorfeus/data/hamster_storage_expander.rb +94 -0
- data/lib/isomorfeus/data/handler/generic.rb +134 -138
- data/lib/isomorfeus/data/reducer.rb +30 -30
- data/lib/isomorfeus/data/version.rb +4 -4
- data/lib/isomorfeus-data.rb +56 -64
- data/lib/isomorfeus_data/lucid_document/base.rb +10 -0
- data/lib/isomorfeus_data/lucid_document/mixin.rb +148 -0
- data/lib/isomorfeus_data/lucid_file/base.rb +10 -0
- data/lib/isomorfeus_data/lucid_file/mixin.rb +217 -0
- data/lib/isomorfeus_data/lucid_object/base.rb +10 -0
- data/lib/isomorfeus_data/lucid_object/mixin.rb +216 -0
- data/lib/isomorfeus_data/lucid_query/base.rb +10 -0
- data/lib/isomorfeus_data/lucid_query/mixin.rb +81 -0
- data/lib/isomorfeus_data/lucid_query_result.rb +97 -0
- data/opal/uri/common.rb +18 -0
- data/opal/uri/generic.rb +47 -0
- data/opal/uri.rb +29 -0
- metadata +85 -96
- data/lib/isomorfeus/data/handler/arango.rb +0 -56
- data/lib/isomorfeus/data/handler/object_call.rb +0 -40
- data/lib/isomorfeus/data/handler/object_store.rb +0 -40
- data/lib/isomorfeus_data/lucid_data/array/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/array/mixin.rb +0 -580
- data/lib/isomorfeus_data/lucid_data/collection/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/collection/finders.rb +0 -83
- data/lib/isomorfeus_data/lucid_data/collection/mixin.rb +0 -737
- data/lib/isomorfeus_data/lucid_data/composition/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/composition/mixin.rb +0 -234
- data/lib/isomorfeus_data/lucid_data/document/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/document/mixin.rb +0 -9
- data/lib/isomorfeus_data/lucid_data/edge/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/edge/mixin.rb +0 -286
- data/lib/isomorfeus_data/lucid_data/edge_collection/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/edge_collection/finders.rb +0 -134
- data/lib/isomorfeus_data/lucid_data/edge_collection/mixin.rb +0 -747
- data/lib/isomorfeus_data/lucid_data/generic_collection.rb +0 -4
- data/lib/isomorfeus_data/lucid_data/generic_edge.rb +0 -4
- data/lib/isomorfeus_data/lucid_data/generic_edge_collection.rb +0 -4
- data/lib/isomorfeus_data/lucid_data/generic_node.rb +0 -4
- data/lib/isomorfeus_data/lucid_data/graph/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/graph/finders.rb +0 -141
- data/lib/isomorfeus_data/lucid_data/graph/mixin.rb +0 -489
- data/lib/isomorfeus_data/lucid_data/hash/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/hash/mixin.rb +0 -427
- data/lib/isomorfeus_data/lucid_data/link/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/link/mixin.rb +0 -9
- data/lib/isomorfeus_data/lucid_data/link_collection/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/link_collection/mixin.rb +0 -9
- data/lib/isomorfeus_data/lucid_data/node/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/node/mixin.rb +0 -232
- data/lib/isomorfeus_data/lucid_data/query/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/query/mixin.rb +0 -83
- data/lib/isomorfeus_data/lucid_data/query_result.rb +0 -95
- data/lib/isomorfeus_data/lucid_data/vertex/base.rb +0 -13
- data/lib/isomorfeus_data/lucid_data/vertex/mixin.rb +0 -9
- data/lib/lucid_arango/collection/base.rb +0 -13
- data/lib/lucid_arango/collection/mixin.rb +0 -18
- data/lib/lucid_arango/document/base.rb +0 -13
- data/lib/lucid_arango/document/mixin.rb +0 -9
- data/lib/lucid_arango/edge/base.rb +0 -13
- data/lib/lucid_arango/edge/mixin.rb +0 -18
- data/lib/lucid_arango/edge_collection/base.rb +0 -13
- data/lib/lucid_arango/edge_collection/mixin.rb +0 -18
- data/lib/lucid_arango/graph/base.rb +0 -13
- data/lib/lucid_arango/graph/mixin.rb +0 -18
- data/lib/lucid_arango/node/base.rb +0 -13
- data/lib/lucid_arango/node/mixin.rb +0 -79
- data/lib/lucid_arango/object/base.rb +0 -11
- data/lib/lucid_arango/object/mixin.rb +0 -158
- data/lib/lucid_arango/remote_object/base.rb +0 -11
- data/lib/lucid_arango/remote_object/mixin.rb +0 -17
- data/lib/lucid_arango/vertex/base.rb +0 -13
- data/lib/lucid_arango/vertex/mixin.rb +0 -9
@@ -0,0 +1,148 @@
|
|
1
|
+
module LucidDocument
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.include(Isomorfeus::Data::FieldSupport)
|
5
|
+
base.extend(Isomorfeus::Data::GenericClassApi)
|
6
|
+
base.include(Isomorfeus::Data::GenericInstanceApi)
|
7
|
+
|
8
|
+
def [](name)
|
9
|
+
send(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def []=(name, val)
|
13
|
+
send("#{name}=", val)
|
14
|
+
end
|
15
|
+
|
16
|
+
def changed!
|
17
|
+
@_changed = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_transport
|
21
|
+
hash = { 'fields' => _get_selected_fields }
|
22
|
+
hash['revision'] = revision if revision
|
23
|
+
result = { @class_name => { @key => hash }}
|
24
|
+
result.deep_merge!(@class_name => { @previous_key => { new_key: @key}}) if @previous_key
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
if RUBY_ENGINE == 'opal'
|
29
|
+
def initialize(key: nil, revision: nil, fields: nil)
|
30
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
31
|
+
@class_name = self.class.name
|
32
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
33
|
+
_update_paths
|
34
|
+
@_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
|
35
|
+
@_changed = false
|
36
|
+
loaded = loaded?
|
37
|
+
if fields
|
38
|
+
if loaded
|
39
|
+
raw_fields = Redux.fetch_by_path(*@_store_path)
|
40
|
+
if `raw_fields === null`
|
41
|
+
@_changed_fields = !fields ? {} : fields
|
42
|
+
elsif raw_fields && !fields.nil? && ::Hash.new(raw_fields) != fields
|
43
|
+
@_changed_fields = fields
|
44
|
+
end
|
45
|
+
else
|
46
|
+
@_changed_fields = fields
|
47
|
+
end
|
48
|
+
else
|
49
|
+
@_changed_fields = {}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def _load_from_store!
|
54
|
+
@_changed_fields = {}
|
55
|
+
@_changed = false
|
56
|
+
end
|
57
|
+
|
58
|
+
def _update_paths
|
59
|
+
@_store_path = [:data_state, @class_name, @key, :fields]
|
60
|
+
end
|
61
|
+
|
62
|
+
def each(&block)
|
63
|
+
fields.each(&block)
|
64
|
+
end
|
65
|
+
else # RUBY_ENGINE
|
66
|
+
Isomorfeus.add_valid_data_class(base) unless base == LucidDocument::Base
|
67
|
+
|
68
|
+
base.instance_exec do
|
69
|
+
def instance_from_transport(instance_data, _included_items_data)
|
70
|
+
key = instance_data[self.name].keys.first
|
71
|
+
revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
|
72
|
+
fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys!(&:to_sym) : nil
|
73
|
+
new(key: key, revision: revision, fields: fields)
|
74
|
+
end
|
75
|
+
|
76
|
+
def setup_index(&block)
|
77
|
+
@_setup_index_block = block
|
78
|
+
end
|
79
|
+
|
80
|
+
def ferret_accelerator
|
81
|
+
return @ferret_accelerator if @ferret_accelerator
|
82
|
+
@ferret_accelerator = if @_setup_index_block
|
83
|
+
Isomorfeus::Data::FerretAccelerator.new(self, &@_setup_index_block)
|
84
|
+
else
|
85
|
+
Isomorfeus::Data::FerretAccelerator.new(self)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def search(query, options = {})
|
90
|
+
top_docs = []
|
91
|
+
self.ferret_accelerator.search_each(query, options) do |id|
|
92
|
+
doc = self.ferret_accelerator.load_doc(id)
|
93
|
+
top_docs << self.new(key: doc[:key], fields: doc) if doc
|
94
|
+
end
|
95
|
+
top_docs
|
96
|
+
end
|
97
|
+
|
98
|
+
execute_create do
|
99
|
+
doc = self.fields
|
100
|
+
doc[:key] = self.key.nil? ? SecureRandom.uuid : self.key
|
101
|
+
self.class.ferret_accelerator.create_doc(doc)
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
execute_destroy do |key:|
|
106
|
+
self.ferret_accelerator.destroy_doc(key)
|
107
|
+
end
|
108
|
+
|
109
|
+
execute_load do |key:|
|
110
|
+
doc = self.ferret_accelerator.load_doc(key)
|
111
|
+
doc.delete(:key)
|
112
|
+
self.new(key: key, fields: doc)
|
113
|
+
end
|
114
|
+
|
115
|
+
execute_save do
|
116
|
+
doc = self.fields
|
117
|
+
if self.key.nil?
|
118
|
+
doc[:key] = SecureRandom.uuid
|
119
|
+
self.class.ferret_accelerator.create_doc(doc)
|
120
|
+
else
|
121
|
+
doc[:key] = self.key
|
122
|
+
self.class.ferret_accelerator.save_doc(self.key, doc)
|
123
|
+
end
|
124
|
+
self
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def initialize(key: nil, revision: nil, fields: nil)
|
129
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
130
|
+
@class_name = self.class.name
|
131
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
132
|
+
@_revision = revision
|
133
|
+
@_changed = false
|
134
|
+
fields = {} unless fields
|
135
|
+
@_raw_fields = fields
|
136
|
+
end
|
137
|
+
|
138
|
+
def _unchange!
|
139
|
+
@_changed = false
|
140
|
+
end
|
141
|
+
|
142
|
+
def each(&block)
|
143
|
+
@_raw_fields.each(&block)
|
144
|
+
end
|
145
|
+
end # RUBY_ENGINE
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module LucidFile
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(Isomorfeus::Data::GenericClassApi)
|
5
|
+
base.include(Isomorfeus::Data::GenericInstanceApi)
|
6
|
+
|
7
|
+
def changed!
|
8
|
+
@_changed = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_transport
|
12
|
+
hash = {}
|
13
|
+
hash['revision'] = revision if revision
|
14
|
+
hash['data_uri'] = data_uri
|
15
|
+
result = { @class_name => { @key => hash }}
|
16
|
+
result.deep_merge!(@class_name => { @previous_key => { new_key: @key }}) if @previous_key
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def content_type
|
21
|
+
_reload
|
22
|
+
return @_data_uri_object.content_type if @_data_uri_object
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def content_type=(c)
|
27
|
+
changed!
|
28
|
+
_content_type(c)
|
29
|
+
end
|
30
|
+
|
31
|
+
def _content_type(c)
|
32
|
+
_reload
|
33
|
+
@_data_uri_string = _format_data_uri(c, @_data_uri_object.data)
|
34
|
+
@_data_uri_object = URI::Data.new(@_data_uri_string)
|
35
|
+
c
|
36
|
+
end
|
37
|
+
|
38
|
+
def data
|
39
|
+
_reload
|
40
|
+
@_data_uri_object.data
|
41
|
+
end
|
42
|
+
|
43
|
+
def data=(d)
|
44
|
+
changed!
|
45
|
+
_data(d)
|
46
|
+
end
|
47
|
+
|
48
|
+
def _data(d)
|
49
|
+
_reload
|
50
|
+
@_data_uri_string = _format_data_uri(self.content_type, d)
|
51
|
+
@_data_uri_object = URI::Data.new(@_data_uri_string)
|
52
|
+
d
|
53
|
+
end
|
54
|
+
|
55
|
+
def data_uri
|
56
|
+
_reload
|
57
|
+
@_data_uri_string
|
58
|
+
end
|
59
|
+
|
60
|
+
def data_uri=(d)
|
61
|
+
changed!
|
62
|
+
_data_uri(d)
|
63
|
+
end
|
64
|
+
|
65
|
+
def _data_uri(d)
|
66
|
+
_reload
|
67
|
+
if d.class == URI::Data
|
68
|
+
@_data_uri_string = _format_data_uri(d.content_type, d.data)
|
69
|
+
@_data_uri_object = d
|
70
|
+
else
|
71
|
+
@_data_uri_string = d
|
72
|
+
@_data_uri_object = URI::Data.new(d)
|
73
|
+
end
|
74
|
+
@_data_uri_string
|
75
|
+
end
|
76
|
+
|
77
|
+
def data_uri_object
|
78
|
+
_reload
|
79
|
+
@_data_uri_object
|
80
|
+
end
|
81
|
+
|
82
|
+
def _format_data_uri(c, d)
|
83
|
+
"data:#{c};base64,#{Base64.encode64(d).chop}"
|
84
|
+
end
|
85
|
+
|
86
|
+
if RUBY_ENGINE == 'opal'
|
87
|
+
base.instance_exec do
|
88
|
+
def files_path
|
89
|
+
end
|
90
|
+
|
91
|
+
def files_path=(_)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialize(key: nil, content_type: nil, data: nil, data_uri: nil, revision: nil)
|
96
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
97
|
+
@class_name = self.class.name
|
98
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
99
|
+
_update_paths
|
100
|
+
@_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
|
101
|
+
@_changed = false
|
102
|
+
@_reload = false
|
103
|
+
loaded = loaded?
|
104
|
+
@_data_uri_object = nil
|
105
|
+
@_data_uri_string = nil
|
106
|
+
if data_uri
|
107
|
+
self.data_uri = data_uri
|
108
|
+
elsif data
|
109
|
+
self.data = data
|
110
|
+
self.content_type = content_type if content_type
|
111
|
+
else
|
112
|
+
self._data('')
|
113
|
+
self._content_type(content_type) if content_type
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def _load_from_store!
|
118
|
+
@_changed = false
|
119
|
+
@_reload = true
|
120
|
+
end
|
121
|
+
|
122
|
+
def _reload
|
123
|
+
return unless @_reload
|
124
|
+
@_reload = false
|
125
|
+
d = Redux.fetch_by_path(*@_store_path)
|
126
|
+
self._data_uri(d) if d
|
127
|
+
end
|
128
|
+
|
129
|
+
def _update_paths
|
130
|
+
@_store_path = [:data_state, @class_name, @key, :data_uri]
|
131
|
+
end
|
132
|
+
else # RUBY_ENGINE
|
133
|
+
Isomorfeus.add_valid_file_class(base) unless base == LucidFile::Base
|
134
|
+
|
135
|
+
base.instance_exec do
|
136
|
+
def instance_from_transport(instance_data, _included_items_data)
|
137
|
+
key = instance_data[self.name].keys.first
|
138
|
+
revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
|
139
|
+
data_uri = instance_data[self.name][key].key?('data_uri') ? instance_data[self.name][key]['data_uri'] : nil
|
140
|
+
new(key: key, revision: revision, data_uri: data_uri)
|
141
|
+
end
|
142
|
+
|
143
|
+
def files_path
|
144
|
+
@files_path ||= Isomorfeus.files_path
|
145
|
+
end
|
146
|
+
|
147
|
+
def files_path=(f)
|
148
|
+
@files_path = f
|
149
|
+
end
|
150
|
+
|
151
|
+
def check_and_prepare_path(key:)
|
152
|
+
Isomorfeus.raise_error(message: 'Invalid key (contains ".." or "\\")') if key.include?('..') || key.include?('\\')
|
153
|
+
elements = key.split('/')
|
154
|
+
Isomorfeus.raise_error(message: 'Invalid key (contains more than 2 slashes "/")') if elements.size > 3
|
155
|
+
file = elements.pop
|
156
|
+
if elements.size > 0
|
157
|
+
dir_path = ::File.expand_path(::File.join(files_path, *elements))
|
158
|
+
FileUtils.mkdir_p(path) unless Dir.exist?(dir_path)
|
159
|
+
::File.join(dir_path, file)
|
160
|
+
else
|
161
|
+
FileUtils.mkdir_p(files_path) unless Dir.exist?(files_path)
|
162
|
+
::File.join(files_path, file)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
execute_create do
|
167
|
+
self.save
|
168
|
+
end
|
169
|
+
|
170
|
+
execute_destroy do |key:|
|
171
|
+
file = check_and_prepare_path(key: key)
|
172
|
+
::FileUtils.rm_f(file)
|
173
|
+
true
|
174
|
+
end
|
175
|
+
|
176
|
+
execute_load do |key:|
|
177
|
+
file = check_and_prepare_path(key: key)
|
178
|
+
d = ::File.read(file)
|
179
|
+
instance = self.new(key: key)
|
180
|
+
instance.data = d
|
181
|
+
instance
|
182
|
+
end
|
183
|
+
|
184
|
+
execute_save do
|
185
|
+
file = self.class.check_and_prepare_path(key: self.key)
|
186
|
+
::File.write(file, self.data)
|
187
|
+
self
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def initialize(key: nil, content_type: nil, data: nil, data_uri: nil, revision: nil)
|
192
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
193
|
+
@class_name = self.class.name
|
194
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
195
|
+
@_revision = revision
|
196
|
+
@_data_uri_object = nil
|
197
|
+
@_data_uri_string = nil
|
198
|
+
if data_uri
|
199
|
+
self._data_uri(data_uri)
|
200
|
+
else
|
201
|
+
self._data(data ? data : '')
|
202
|
+
self._content_type(content_type) if content_type
|
203
|
+
end
|
204
|
+
@_changed = false
|
205
|
+
end
|
206
|
+
|
207
|
+
def _reload
|
208
|
+
end
|
209
|
+
|
210
|
+
def _unchange!
|
211
|
+
@_data_uri = @_changed_data_uri if @_changed
|
212
|
+
@_changed = false
|
213
|
+
end
|
214
|
+
end # RUBY_ENGINE
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
module LucidObject
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.include(Isomorfeus::Data::AttributeSupport)
|
5
|
+
base.extend(Isomorfeus::Data::GenericClassApi)
|
6
|
+
base.include(Isomorfeus::Data::GenericInstanceApi)
|
7
|
+
|
8
|
+
def changed!
|
9
|
+
@_changed = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](name)
|
13
|
+
send(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(name, val)
|
17
|
+
send("#{name}=".to_sym, val)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_transport
|
21
|
+
hash = { 'attributes' => _get_selected_attributes }
|
22
|
+
hash['revision'] = revision if revision
|
23
|
+
result = { @class_name => { @key => hash }}
|
24
|
+
result.deep_merge!(@class_name => { @previous_key => { new_key: @key}}) if @previous_key
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
if RUBY_ENGINE == 'opal'
|
29
|
+
def initialize(key: nil, revision: nil, attributes: nil)
|
30
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
31
|
+
@class_name = self.class.name
|
32
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
33
|
+
_update_paths
|
34
|
+
@_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
|
35
|
+
@_changed = false
|
36
|
+
loaded = loaded?
|
37
|
+
if attributes
|
38
|
+
_validate_attributes(attributes)
|
39
|
+
if loaded
|
40
|
+
raw_attributes = Redux.fetch_by_path(*@_store_path)
|
41
|
+
if `raw_attributes === null`
|
42
|
+
@_changed_attributes = !attributes ? {} : attributes
|
43
|
+
elsif raw_attributes && !attributes.nil? && ::Hash.new(raw_attributes) != attributes
|
44
|
+
@_changed_attributes = attributes
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@_changed_attributes = attributes
|
48
|
+
end
|
49
|
+
else
|
50
|
+
@_changed_attributes = {}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def _load_from_store!
|
55
|
+
@_changed_attributes = {}
|
56
|
+
@_changed = false
|
57
|
+
end
|
58
|
+
|
59
|
+
def _update_paths
|
60
|
+
@_store_path = [:data_state, @class_name, @key, :attributes]
|
61
|
+
end
|
62
|
+
|
63
|
+
def each(&block)
|
64
|
+
attributes.each(&block)
|
65
|
+
end
|
66
|
+
else # RUBY_ENGINE
|
67
|
+
Isomorfeus.add_valid_data_class(base) unless base == LucidObject::Base
|
68
|
+
|
69
|
+
base.instance_exec do
|
70
|
+
def instance_from_transport(instance_data, _included_items_data)
|
71
|
+
key = instance_data[self.name].keys.first
|
72
|
+
revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
|
73
|
+
attributes = instance_data[self.name][key].key?('attributes') ? instance_data[self.name][key]['attributes'].transform_keys!(&:to_sym) : nil
|
74
|
+
new(key: key, revision: revision, attributes: attributes)
|
75
|
+
end
|
76
|
+
|
77
|
+
def setup_environment(&block)
|
78
|
+
@_setup_environment_block = block
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_index(&block)
|
82
|
+
@_setup_index_block = block
|
83
|
+
end
|
84
|
+
|
85
|
+
def hamster_storage_expander
|
86
|
+
return @hamster_storage_expander if @hamster_storage_expander
|
87
|
+
@hamster_storage_expander = if @_setup_environment_block
|
88
|
+
Isomorfeus::Data::HamsterStorageExpander.new(&@_setup_index_block)
|
89
|
+
else
|
90
|
+
Isomorfeus::Data::HamsterStorageExpander.new
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def hamster_accelerator
|
95
|
+
return @hamster_accelerator if @hamster_accelerator
|
96
|
+
@hamster_accelerator = if @_setup_index_block
|
97
|
+
Isomorfeus::Data::HamsterAccelerator.new(&@_setup_index_block)
|
98
|
+
else
|
99
|
+
Isomorfeus::Data::HamsterAccelerator.new
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def search(attr, val, options = {})
|
104
|
+
idx_type = self.indexed_attributes[attr]
|
105
|
+
raise "Can only search indexed attributes, but attribute :#{attr} is not indexed!" unless idx_type
|
106
|
+
objs = []
|
107
|
+
if idx_type == :text
|
108
|
+
query = "+value:#{val} +class_name:#{self.name}"
|
109
|
+
query << " +attribute:#{attr}" if attr != '*'
|
110
|
+
self.hamster_accelerator.search_each(query, options) do |id|
|
111
|
+
doc = self.hamster_accelerator.load_doc(id)
|
112
|
+
if doc
|
113
|
+
sid_s = doc[:sid_s_attr].split(':|:')[0]
|
114
|
+
obj = self.load(key: sid_s)
|
115
|
+
objs << obj if obj
|
116
|
+
end
|
117
|
+
end
|
118
|
+
else
|
119
|
+
attr_s = ":[#{attr}]"
|
120
|
+
accept_all_attr = attr_s == ":[*]" ? true : false
|
121
|
+
self.hamster_storage_expander.search(":[:#{val}:]:") do |sid_s_attr|
|
122
|
+
if accept_all_attr || sid_s_attr.end_with?(attr_s)
|
123
|
+
sid_s = sid_s_attr.split(':|:[')[0]
|
124
|
+
obj = self.load(key: sid_s)
|
125
|
+
objs << obj if obj
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
objs
|
130
|
+
end
|
131
|
+
|
132
|
+
execute_create do
|
133
|
+
self.key = SecureRandom.uuid unless self.key
|
134
|
+
self.class.hamster_storage_expander.create_object(self.sid_s, self)
|
135
|
+
self.class.indexed_attributes.each do |attr, idx_type|
|
136
|
+
if idx_type == :text
|
137
|
+
self._store_text_indexed_attribute(attr)
|
138
|
+
else
|
139
|
+
self._store_value_indexed_attribute(attr)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
execute_destroy do |key:|
|
146
|
+
key = key.to_s
|
147
|
+
sid_s = key.start_with?('[') ? key : gen_sid_s(key)
|
148
|
+
self.hamster_storage_expander.destroy_object(sid_s)
|
149
|
+
self.indexed_attributes.each do |attr, idx_type|
|
150
|
+
if idx_type == :text
|
151
|
+
self.hamster_accelerator.destroy_doc("#{sid_s}:|:[#{attr}]")
|
152
|
+
else
|
153
|
+
old_val = self.hamster_storage_expander.index_get("#{sid_s}:|:[#{attr}]")
|
154
|
+
self.hamster_storage_expander.index_delete("#{sid_s}:|:[#{attr}]", old_val)
|
155
|
+
self.hamster_storage_expander.index_delete(":[:#{old_val}:]:", "#{sid_s}:|:[#{attr}]")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
execute_load do |key:|
|
162
|
+
key = key.to_s
|
163
|
+
sid_s = key.start_with?('[') ? key : gen_sid_s(key)
|
164
|
+
self.hamster_storage_expander.load_object(sid_s)
|
165
|
+
end
|
166
|
+
|
167
|
+
execute_save do
|
168
|
+
self.key = SecureRandom.uuid unless self.key
|
169
|
+
self.class.hamster_storage_expander.save_object(self.sid_s, self)
|
170
|
+
self.class.indexed_attributes.each do |attr, val|
|
171
|
+
if val == :text
|
172
|
+
self._store_text_indexed_attribute(attr)
|
173
|
+
else
|
174
|
+
self._store_value_indexed_attribute(attr)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
self
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def initialize(key: nil, revision: nil, attributes: nil)
|
182
|
+
@key = key.nil? ? SecureRandom.uuid : key.to_s
|
183
|
+
@class_name = self.class.name
|
184
|
+
@class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
|
185
|
+
@_revision = revision
|
186
|
+
@_changed = false
|
187
|
+
attributes = {} unless attributes
|
188
|
+
_validate_attributes(attributes) if attributes
|
189
|
+
@_raw_attributes = attributes
|
190
|
+
end
|
191
|
+
|
192
|
+
def _store_text_indexed_attribute(attr)
|
193
|
+
doc = { sid_s_attr: "#{self.sid_s}:|:[#{attr}]", value: self.send(attr).to_s, attribute: attr.to_s, class_name: @class_name }
|
194
|
+
self.class.hamster_accelerator.save_doc("#{self.sid_s}:|:[#{attr}]", doc)
|
195
|
+
end
|
196
|
+
|
197
|
+
def _store_value_indexed_attribute(attr)
|
198
|
+
old_val = self.class.hamster_storage_expander.index_get("#{self.sid_s}:|:[#{attr}]")
|
199
|
+
self.class.hamster_storage_expander.index_delete("#{self.sid_s}:|:[#{attr}]", old_val)
|
200
|
+
self.class.hamster_storage_expander.index_delete(":[:#{old_val}:]:", "#{self.sid_s}:|:[#{attr}]")
|
201
|
+
val = "#{self.send(attr)}"[0..300]
|
202
|
+
self.class.hamster_storage_expander.index_put("#{self.sid_s}:|:[#{attr}]", val)
|
203
|
+
self.class.hamster_storage_expander.index_put(":[:#{val}:]:", "#{self.sid_s}:|:[#{attr}]")
|
204
|
+
end
|
205
|
+
|
206
|
+
def _unchange!
|
207
|
+
@_changed = false
|
208
|
+
end
|
209
|
+
|
210
|
+
def each(&block)
|
211
|
+
@_raw_attributes.each(&block)
|
212
|
+
end
|
213
|
+
end # RUBY_ENGINE
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module LucidQuery
|
2
|
+
module Mixin
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(LucidPropDeclaration::Mixin)
|
5
|
+
|
6
|
+
if RUBY_ENGINE == 'opal'
|
7
|
+
base.instance_exec do
|
8
|
+
def execute(**props)
|
9
|
+
props[:query_result_instance] = LucidQueryResult.new
|
10
|
+
promise_execute(props) unless props[:query_result_instance].loaded?
|
11
|
+
props[:query_result_instance]
|
12
|
+
end
|
13
|
+
|
14
|
+
def promise_execute(**props)
|
15
|
+
query_result_instance = props.delete(:query_result_instance)
|
16
|
+
query_result_instance = LucidQueryResult.new unless query_result_instance
|
17
|
+
props.each_key do |prop_name|
|
18
|
+
Isomorfeus.raise_error(message: "#{self.to_s} No such query prop declared: '#{prop_name}'!") unless declared_props.key?(prop_name)
|
19
|
+
end
|
20
|
+
props = validated_props(props)
|
21
|
+
props[:query_result_instance_key] = query_result_instance.key
|
22
|
+
Isomorfeus::Transport.promise_send_path( 'Isomorfeus::Data::Handler::Generic', self.name, :query, props).then do |agent|
|
23
|
+
if agent.processed
|
24
|
+
agent.result
|
25
|
+
else
|
26
|
+
agent.processed = true
|
27
|
+
if agent.response.key?(:error)
|
28
|
+
Isomorfeus.raise_error(message: agent.response[:error])
|
29
|
+
end
|
30
|
+
query_result_instance._load_from_store!
|
31
|
+
Isomorfeus.store.dispatch(type: 'DATA_LOAD', data: agent.full_response[:data])
|
32
|
+
agent.result = query_result_instance
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def execute_query(_); end
|
38
|
+
end
|
39
|
+
else
|
40
|
+
unless base == LucidQuery::Base
|
41
|
+
Isomorfeus.add_valid_data_class(base)
|
42
|
+
end
|
43
|
+
|
44
|
+
base.instance_exec do
|
45
|
+
def promise_execute(**props)
|
46
|
+
instance = self.execute(**props)
|
47
|
+
result_promise = Promise.new
|
48
|
+
result_promise.resolve(instance)
|
49
|
+
result_promise
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute(**props)
|
53
|
+
query_result_instance_key = props.delete(:query_result_instance_key)
|
54
|
+
query_result = LucidQueryResult.new(key: query_result_instance_key)
|
55
|
+
query_result.result_set = self.new(**props).instance_exec(&@_query_block)
|
56
|
+
query_result
|
57
|
+
end
|
58
|
+
|
59
|
+
def execute_query(&block)
|
60
|
+
@_query_block = block
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_reader :props
|
65
|
+
|
66
|
+
def initialize(**props_hash)
|
67
|
+
props_hash = self.class.validated_props(props_hash)
|
68
|
+
@props = LucidProps.new(props_hash)
|
69
|
+
end
|
70
|
+
|
71
|
+
def current_user
|
72
|
+
Isomorfeus.current_user
|
73
|
+
end
|
74
|
+
|
75
|
+
def pub_sub_client
|
76
|
+
Isomorfeus.pub_sub_client
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|