isomorfeus-data 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,14 @@
1
1
  module LucidObject
2
2
  module Mixin
3
3
  def self.included(base)
4
- base.include(Isomorfeus::Data::AttributeSupport)
4
+ base.include(Isomorfeus::Data::FieldSupport)
5
5
  base.extend(Isomorfeus::Data::GenericClassApi)
6
6
  base.include(Isomorfeus::Data::GenericInstanceApi)
7
7
  base.include(LucidI18n::Mixin)
8
8
 
9
9
  base.instance_exec do
10
- def store_compressed(quality: 5)
11
- @_store_compressed = quality
12
- end
13
-
14
- def _store_compressed
15
- @_store_compressed
10
+ def escape_string(s)
11
+ s.gsub(/([\\\&\:\(\)\[\]\{\}\!\"\~\^\|\<\>\=\*\?\+\-\s])/, '\\\\\1')
16
12
  end
17
13
  end
18
14
 
@@ -29,220 +25,186 @@ module LucidObject
29
25
  end
30
26
 
31
27
  def to_transport
32
- hash = { 'attributes' => _get_selected_attributes }
28
+ hash = { 'fields' => _get_selected_fields }
33
29
  hash['revision'] = revision if revision
34
30
  result = { @class_name => { @key => hash }}
35
- result.deep_merge!(@class_name => { @previous_key => { new_key: @key}}) if @previous_key
31
+ result.deep_merge!(@class_name => { @previous_key => { new_key: @key }}) if @previous_key
36
32
  result
37
33
  end
38
34
 
35
+ def included_items_to_transport
36
+ f = fields
37
+ data_hash = {}
38
+ self.class.field_types.each do |field, type|
39
+ if type == :object
40
+ v = f[field]
41
+ if v
42
+ data_hash.deep_merge!(v.to_transport)
43
+ if v.respond_to?(:included_items_to_transport)
44
+ data_hash.deep_merge!(v.included_items_to_transport)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ data_hash
50
+ end
51
+
39
52
  if RUBY_ENGINE == 'opal'
40
- def initialize(key: nil, revision: nil, attributes: nil, _loading: false)
53
+ def initialize(key: nil, revision: nil, fields: nil, _loading: false, attributes: nil)
41
54
  @key = key.nil? ? SecureRandom.uuid : key.to_s
42
55
  @class_name = self.class.name
43
56
  @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
44
57
  _update_paths
45
58
  @_revision = revision ? revision : Redux.fetch_by_path(:data_state, :revision, @class_name, @key)
59
+ @_objects = {}
46
60
  @_changed = false
47
61
  loaded = loaded?
62
+ fields = attributes if attributes
48
63
  if loaded
49
- raw_attributes = Redux.fetch_by_path(*@_store_path)
50
- if `raw_attributes === null`
51
- if attributes
52
- _validate_attributes(attributes)
53
- @_changed_attributes = attributes
64
+ raw_fields = Redux.fetch_by_path(*@_store_path)
65
+ if `raw_fields === null`
66
+ if fields
67
+ _validate_fields(fields)
68
+ @_changed_fields = fields
54
69
  else
55
- @_changed_attributes = {}
70
+ @_changed_fields = {}
56
71
  end
57
- elsif raw_attributes && attributes && ::Hash.new(raw_attributes) != attributes
58
- _validate_attributes(attributes)
59
- @_changed_attributes = attributes
72
+ elsif raw_fields && fields && ::Hash.new(raw_fields) != fields
73
+ _validate_fields(fields)
74
+ @_changed_fields = fields
60
75
  else
61
- @_changed_attributes = {}
76
+ @_changed_fields = {}
62
77
  end
63
78
  else
64
- attributes = {} unless attributes
65
- _validate_attributes(attributes) unless _loading
66
- @_changed_attributes = attributes
79
+ fields = {} unless fields
80
+ _validate_fields(fields) unless _loading
81
+ @_changed_fields = fields
67
82
  end
68
83
  end
69
84
 
70
85
  def _load_from_store!
71
- @_changed_attributes = {}
86
+ @_changed_fields = {}
87
+ @_objects = {}
72
88
  @_changed = false
73
89
  end
74
90
 
75
91
  def _update_paths
76
- @_store_path = [:data_state, @class_name, @key, :attributes]
92
+ @_store_path = [:data_state, @class_name, @key, :fields]
77
93
  end
78
94
 
79
95
  def each(&block)
80
- attributes.each(&block)
96
+ fields.each(&block)
81
97
  end
82
98
  else # RUBY_ENGINE
83
99
  Isomorfeus.add_valid_data_class(base) unless base == LucidObject::Base
84
100
 
85
101
  base.instance_exec do
86
- def instance_from_transport(instance_data, _included_items_data)
102
+ def instance_from_transport(instance_data, included_items_data, _already_loaded = {})
87
103
  key = instance_data[self.name].keys.first
104
+ ref_s = gen_ref_s(key)
105
+ return _already_loaded[ref_s] if _already_loaded.key?(ref_s)
88
106
  revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
89
- attributes = instance_data[self.name][key].key?('attributes') ? instance_data[self.name][key]['attributes'].transform_keys!(&:to_sym) : nil
90
- new(key: key, revision: revision, attributes: attributes)
107
+ data_obj = new(key: key, revision: revision)
108
+ _already_loaded[ref_s] = data_obj
109
+ fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys(&:to_sym) : nil
110
+ if fields
111
+ field_types.each do |field, type|
112
+ if type == :object
113
+ sid = fields[field]
114
+ if sid
115
+ o_class_name = sid[0]
116
+ raise "invalid data class #{type_class_name}" unless Isomorfeus.valid_data_class_name?(o_class_name)
117
+ o_class = Isomorfeus.cached_data_class(o_class_name)
118
+ o_data = { o_class_name => { sid[1] => included_items_data[o_class_name][sid[1]] }}
119
+ if included_items_data && !included_items_data[self.name]&.key?(key)
120
+ included_items_data.deep_merge!(instance_data)
121
+ end
122
+ fields[field] = o_class.instance_from_transport(o_data, included_items_data, _already_loaded)
123
+ end
124
+ end
125
+ end
126
+ end
127
+ data_obj._validate_fields(fields)
128
+ data_obj.fields.merge!(fields)
129
+ data_obj
91
130
  end
92
131
 
93
132
  def props_from_data(instance_data)
94
133
  key = instance_data[self.name].keys.first
95
134
  revision = instance_data[self.name][key].key?('revision') ? instance_data[self.name][key]['revision'] : nil
96
- attributes = instance_data[self.name][key].key?('attributes') ? instance_data[self.name][key]['attributes'].transform_keys!(&:to_sym) : nil
97
- LucidProps.new({ key: key, revision: revision }.merge!(attributes))
98
- end
99
-
100
- def setup_environment(&block)
101
- @_setup_environment_block = block
102
- end
103
-
104
- def setup_index(&block)
105
- @_setup_index_block = block
106
- end
107
-
108
- def object_expander
109
- return @object_expander if @object_expander
110
- compress = _store_compressed
111
- compress = false if compress.nil?
112
- @object_expander = if @_setup_environment_block
113
- Isomorfeus::Data::ObjectExpander.new(class_name: self.to_s, compress: compress, &@_setup_index_block)
114
- else
115
- Isomorfeus::Data::ObjectExpander.new(class_name: self.to_s, compress: compress)
116
- end
135
+ fields = instance_data[self.name][key].key?('fields') ? instance_data[self.name][key]['fields'].transform_keys!(&:to_sym) : nil
136
+ LucidProps.new({ key: key, revision: revision }.merge!(fields))
117
137
  end
118
138
 
119
139
  def object_accelerator
120
- return @object_accelerator if @object_accelerator
121
- @object_accelerator = if @_setup_index_block
122
- Isomorfeus::Data::ObjectAccelerator.new(self.to_s, &@_setup_index_block)
123
- else
124
- Isomorfeus::Data::ObjectAccelerator.new(self.to_s)
125
- end
140
+ @object_accelerator ||= Isomorfeus::Data::ObjectAccelerator.new(self)
126
141
  end
127
142
 
128
- def each(readonly: true, &block)
129
- self.object_expander.each(readonly: readonly) do |obj|
130
- block.call(obj) if obj.class == self
143
+ def each(&block)
144
+ self.object_accelerator.each do |fields|
145
+ block.call self.new(key: fields.delete(:key), fields: fields)
131
146
  end
132
147
  end
133
148
 
134
- def search(attr, val, options = {})
135
- idx_type = self.indexed_attributes[attr]
136
- raise "Can only search indexed attributes, but attribute :#{attr} is not indexed!" unless idx_type
149
+ def search(field = nil, val = nil, options = {}, query: nil)
150
+ if field && !self.field_options[field]&.fetch(:index) == :yes
151
+ raise "Can only search indexed #{self.field_types{field}}s, but #{self.field_types{field}} :#{field} is not indexed!"
152
+ end
137
153
  objs = []
138
- if idx_type == :text
139
- query = "+value:#{val} +class_name:#{self.name}"
140
- query << " +attribute:#{attr}" if attr != '*'
141
- self.object_accelerator.search_each(query, options) do |id|
142
- doc = self.object_accelerator.index.doc(id)&.load
143
- if doc
144
- sid_s = doc[:sid_s_attr].split(':|:')[0]
145
- obj = self.load(key: sid_s)
146
- objs << obj if obj
147
- end
148
- end
149
- else
150
- if val == '*'
151
- self.object_expander.each do |obj|
152
- objs << obj if obj.class == self
153
- end
154
- else
155
- attr_s = ":[#{attr}]"
156
- accept_all_attr = attr_s == ":[*]" ? true : false
157
- self.object_expander.search(":[#{self.name}]:|:[:#{val}:]:") do |sid_s_attr|
158
- if accept_all_attr || sid_s_attr.end_with?(attr_s)
159
- sid_s = sid_s_attr.split(':|:[')[0]
160
- obj = self.load(key: sid_s)
161
- objs << obj if obj
162
- end
163
- end
164
- end
154
+ query = query ? query : "#{field}:#{val}"
155
+ self.object_accelerator.search_each(query, options) do |id|
156
+ fields = self.object_accelerator.load_object(id: id)
157
+ objs << self.new(key: fields.delete(:key), fields: fields)
165
158
  end
166
159
  objs
167
160
  end
168
161
 
169
- execute_create do
162
+ execute_create do |_already_saved: {}|
170
163
  self.key = SecureRandom.uuid unless self.key
171
- self.class.object_expander.create_object(self.sid_s, self)
172
- self.class.indexed_attributes.each do |attr, idx_type|
173
- if idx_type == :text
174
- self._create_text_indexed_attribute(attr)
175
- else
176
- self._store_value_indexed_attribute(attr)
177
- end
164
+ unless _already_saved.key?(self.ref_s)
165
+ _already_saved[self.ref_s] = self
166
+ self.class.object_accelerator.create_object(self.key, fields, _already_saved)
178
167
  end
179
168
  self
180
169
  end
181
170
 
182
171
  execute_destroy do |key:|
183
- key = key.to_s
184
- sid_s = key.start_with?('[') ? key : gen_sid_s(key)
185
- self.object_expander.destroy_object(sid_s)
186
- self.indexed_attributes.each do |attr, idx_type|
187
- if idx_type == :text
188
- self.object_accelerator.destroy_doc("#{sid_s}:|:[#{attr}]")
189
- else
190
- old_val = self.object_expander.index_get("#{sid_s}:|:[#{attr}]")
191
- self.object_expander.index_delete("#{sid_s}:|:[#{attr}]", old_val)
192
- self.object_expander.index_delete(":[#{self.name}]:|:[:#{old_val}:]:", "#{sid_s}:|:[#{attr}]")
193
- end
194
- end
172
+ self.object_accelerator.destroy_object(key.to_s)
195
173
  true
196
174
  end
197
175
 
198
- execute_load do |key:|
199
- key = key.to_s
200
- sid_s = key.start_with?('[') ? key : gen_sid_s(key)
201
- self.object_expander.load_object(sid_s)
176
+ execute_load do |key:, _already_loaded: {}|
177
+ ref_s = self.gen_ref_s(@key)
178
+ if _already_loaded.key?(ref_s)
179
+ _already_loaded[ref_s]
180
+ else
181
+ _already_loaded[ref_s] = true
182
+ fields = self.object_accelerator.load_object(key: key.to_s, already_loaded: _already_loaded)
183
+ obj = fields ? self.new(key: fields.delete(:key), fields: fields) : nil
184
+ _already_loaded[ref_s] = obj
185
+ end
202
186
  end
203
187
 
204
- execute_save do
188
+ execute_save do |_already_saved: {}|
205
189
  self.key = SecureRandom.uuid unless self.key
206
- self.class.object_expander.save_object(self.sid_s, self)
207
- self.class.indexed_attributes.each do |attr, val|
208
- if val == :text
209
- self._store_text_indexed_attribute(attr)
210
- else
211
- self._store_value_indexed_attribute(attr)
212
- end
190
+ unless _already_saved.key?(self.ref_s)
191
+ _already_saved[self.ref_s] = true
192
+ self.class.object_accelerator.save_object(self.key, fields, _already_saved)
213
193
  end
214
194
  self
215
195
  end
216
196
  end
217
197
 
218
- def initialize(key: nil, revision: nil, attributes: nil)
198
+ def initialize(key: nil, revision: nil, fields: nil, attributes: nil)
219
199
  @key = key.nil? ? SecureRandom.uuid : key.to_s
220
200
  @class_name = self.class.name
221
201
  @class_name = @class_name.split('>::').last if @class_name.start_with?('#<')
222
202
  @_revision = revision
223
203
  @_changed = false
224
- attributes = {} unless attributes
225
- _validate_attributes(attributes) if attributes
226
- @_raw_attributes = attributes
227
- end
228
-
229
- def _create_text_indexed_attribute(attr)
230
- doc = { sid_s_attr: "#{self.sid_s}:|:[#{attr}]", value: self.send(attr).to_s, attribute: attr.to_s, class_name: @class_name }
231
- self.class.object_accelerator.create_doc(doc)
232
- end
233
-
234
- def _store_text_indexed_attribute(attr)
235
- doc = { sid_s_attr: "#{self.sid_s}:|:[#{attr}]", value: self.send(attr).to_s, attribute: attr.to_s, class_name: @class_name }
236
- self.class.object_accelerator.save_doc("#{self.sid_s}:|:[#{attr}]", doc)
237
- end
238
-
239
- def _store_value_indexed_attribute(attr)
240
- old_val = self.class.object_expander.index_get("#{self.sid_s}:|:[#{attr}]")
241
- self.class.object_expander.index_delete("#{self.sid_s}:|:[#{attr}]", old_val)
242
- self.class.object_expander.index_delete(":[#{self.class.name}]:|:[:#{old_val}:]:", "#{self.sid_s}:|:[#{attr}]")
243
- val = "#{self.send(attr)}"[0..300]
244
- self.class.object_expander.index_put("#{self.sid_s}:|:[#{attr}]", val)
245
- self.class.object_expander.index_put(":[#{self.class.name}]:|:[:#{val}:]:", "#{self.sid_s}:|:[#{attr}]")
204
+ fields = attributes if attributes
205
+ fields = {} unless fields
206
+ _validate_fields(fields) if fields
207
+ @_raw_fields = fields
246
208
  end
247
209
 
248
210
  def _unchange!
@@ -250,12 +212,12 @@ module LucidObject
250
212
  end
251
213
 
252
214
  def each(&block)
253
- @_raw_attributes.each(&block)
215
+ @_raw_fields.each(&block)
254
216
  end
255
217
 
256
218
  def reload
257
219
  new_instance = self.class.load(key: @key)
258
- @_raw_attributes = new_instance.attributes
220
+ @_raw_fields = new_instance.fields
259
221
  _unchange!
260
222
  self
261
223
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isomorfeus-data
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-19 00:00:00.000000000 Z
11
+ date: 2022-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.13.11
33
+ version: 3.13.13
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 3.13.11
40
+ version: 3.13.13
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: opal
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -86,70 +86,56 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.13.3
89
+ version: 0.14.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.13.3
97
- - !ruby/object:Gem::Dependency
98
- name: isomorfeus-hamster
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 0.6.7
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: 0.6.7
96
+ version: 0.14.0
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: isomorfeus-i18n
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - '='
116
102
  - !ruby/object:Gem::Version
117
- version: 2.4.0
103
+ version: 2.5.0
118
104
  type: :runtime
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - '='
123
109
  - !ruby/object:Gem::Version
124
- version: 2.4.0
110
+ version: 2.5.0
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: isomorfeus-policy
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - '='
130
116
  - !ruby/object:Gem::Version
131
- version: 2.4.0
117
+ version: 2.5.0
132
118
  type: :runtime
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
122
  - - '='
137
123
  - !ruby/object:Gem::Version
138
- version: 2.4.0
124
+ version: 2.5.0
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: isomorfeus-preact
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
129
  - - "~>"
144
130
  - !ruby/object:Gem::Version
145
- version: 10.7.0
131
+ version: 10.7.2
146
132
  type: :runtime
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
136
  - - "~>"
151
137
  - !ruby/object:Gem::Version
152
- version: 10.7.0
138
+ version: 10.7.2
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: isomorfeus-redux
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -170,28 +156,28 @@ dependencies:
170
156
  requirements:
171
157
  - - '='
172
158
  - !ruby/object:Gem::Version
173
- version: 2.4.0
159
+ version: 2.5.0
174
160
  type: :runtime
175
161
  prerelease: false
176
162
  version_requirements: !ruby/object:Gem::Requirement
177
163
  requirements:
178
164
  - - '='
179
165
  - !ruby/object:Gem::Version
180
- version: 2.4.0
166
+ version: 2.5.0
181
167
  - !ruby/object:Gem::Dependency
182
168
  name: isomorfeus
183
169
  requirement: !ruby/object:Gem::Requirement
184
170
  requirements:
185
171
  - - '='
186
172
  - !ruby/object:Gem::Version
187
- version: 2.4.0
173
+ version: 2.5.0
188
174
  type: :development
189
175
  prerelease: false
190
176
  version_requirements: !ruby/object:Gem::Requirement
191
177
  requirements:
192
178
  - - '='
193
179
  - !ruby/object:Gem::Version
194
- version: 2.4.0
180
+ version: 2.5.0
195
181
  - !ruby/object:Gem::Dependency
196
182
  name: rake
197
183
  requirement: !ruby/object:Gem::Requirement
@@ -232,19 +218,14 @@ files:
232
218
  - lib/data_uri/open_uri.rb
233
219
  - lib/data_uri/uri.rb
234
220
  - lib/isomorfeus-data.rb
235
- - lib/isomorfeus/data/attribute_support.rb
236
221
  - lib/isomorfeus/data/config.rb
237
- - lib/isomorfeus/data/document_accelerator.rb
238
222
  - lib/isomorfeus/data/field_support.rb
239
223
  - lib/isomorfeus/data/generic_class_api.rb
240
224
  - lib/isomorfeus/data/generic_instance_api.rb
241
225
  - lib/isomorfeus/data/handler/generic.rb
242
226
  - lib/isomorfeus/data/object_accelerator.rb
243
- - lib/isomorfeus/data/object_expander.rb
244
227
  - lib/isomorfeus/data/reducer.rb
245
228
  - lib/isomorfeus/data/version.rb
246
- - lib/isomorfeus_data/lucid_document/base.rb
247
- - lib/isomorfeus_data/lucid_document/mixin.rb
248
229
  - lib/isomorfeus_data/lucid_file/base.rb
249
230
  - lib/isomorfeus_data/lucid_file/mixin.rb
250
231
  - lib/isomorfeus_data/lucid_object/base.rb