isomorfeus-data 2.4.0 → 2.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.
@@ -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