isomorfeus-data 2.4.2 → 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.2
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-05-28 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
@@ -94,48 +94,34 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.14.0
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
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.2
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.2
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.2
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.2
124
+ version: 2.5.0
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: isomorfeus-preact
141
127
  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.2
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.2
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.2
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.2
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
@@ -1,174 +0,0 @@
1
- module Isomorfeus
2
- module Data
3
- module AttributeSupport
4
- def self.included(base)
5
- base.instance_exec do
6
- def attribute_conditions
7
- @attribute_conditions ||= {}
8
- end
9
-
10
- def indexed_attributes
11
- @indexed_attributes ||= {}
12
- end
13
-
14
- def valid_attribute?(attr_name, val)
15
- Isomorfeus::Props::Validator.new(self.name, attr_name, val, attribute_conditions[attr_name]).validate!
16
- rescue
17
- false
18
- end
19
-
20
- def validate
21
- Isomorfeus::Props::ValidateHashProxy.new
22
- end
23
-
24
- def _validate_attribute(attr_name, val)
25
- Isomorfeus.raise_error(message: "#{self.name}: No such attribute declared: '#{attr_name}'!") unless attribute_conditions.key?(attr_name)
26
- Isomorfeus::Props::Validator.new(self.name, attr_name, val, attribute_conditions[attr_name]).validated_value
27
- end
28
-
29
- def _validate_attributes(attrs)
30
- attribute_conditions.each_key do |attr_name|
31
- if attribute_conditions[attr_name].key?(:required) && attribute_conditions[attr_name][:required] && !attrs.key?(attr_name)
32
- Isomorfeus.raise_error(message: "Required attribute #{attr_name} not given!")
33
- end
34
- attrs[attr_name] = _validate_attribute(attr_name, attrs[attr_name])
35
- end
36
- end
37
- end
38
-
39
- def _validate_attribute(attr_name, val)
40
- self.class._validate_attribute(attr_name, val)
41
- end
42
-
43
- def _validate_attributes(attrs)
44
- self.class._validate_attributes(attrs)
45
- end
46
-
47
- def exclude_attributes(*attrs)
48
- @_excluded_attributes = attrs
49
- end
50
-
51
- def select_attributes(*attrs)
52
- @_selected_attributes = attrs
53
- end
54
-
55
- if RUBY_ENGINE == 'opal'
56
- base.instance_exec do
57
- def attribute(name, options = {})
58
- indexed_attributes[name] = options.delete(:index) if options.key?(:index)
59
- attribute_conditions[name] = options
60
-
61
- define_method(name) do
62
- _get_attribute(name)
63
- end
64
-
65
- define_method("#{name}=") do |val|
66
- val = _validate_attribute(name, val)
67
- changed!
68
- @_changed_attributes[name] = val
69
- end
70
- end
71
- end
72
-
73
- def validate_attributes_function
74
- %x{
75
- if (typeof self.validate_attributes_function === 'undefined') {
76
- self.validate_attributes_function = function(attributes_object) {
77
- try { self.$_validate_attributes(Opal.Hash.$new(attributes_object)) }
78
- catch (e) { return e.message; }
79
- }
80
- }
81
- return self.validate_attributes_function;
82
- }
83
- end
84
-
85
- def validate_attribute_function(attr)
86
- function_name = "validate_attribute_#{attr}_function"
87
- %x{
88
- if (typeof self[function_name] === 'undefined') {
89
- self[function_name] = function(value) {
90
- try { self.$_validate_attribute(attribute, value); }
91
- catch (e) { return e.message; }
92
- }
93
- }
94
- return self[function_name];
95
- }
96
- end
97
-
98
- def _get_attribute(name)
99
- return @_changed_attributes[name] if @_changed_attributes.key?(name)
100
- path = @_store_path + [name]
101
- result = Redux.fetch_by_path(*path)
102
- %x{
103
- if (result === null) { return nil; }
104
- else if (result instanceof Object && !(result instanceof Array)) {
105
- return Opal.Hash.$new(result);
106
- } else { return result; }
107
- }
108
- end
109
-
110
- def attributes
111
- raw_attributes = Redux.fetch_by_path(*@_store_path)
112
- hash = Hash.new(raw_attributes)
113
- hash.merge!(@_changed_attributes) if @_changed_attributes
114
- hash
115
- end
116
-
117
- def _get_selected_attributes
118
- sel_attributes = attributes.dup
119
- if @_selected_attributes && !@_selected_attributes.empty?
120
- sel_attributes.each_key do |attr|
121
- unless @_selected_attributes.include?(attr) || @_selected_attributes.include?(attr)
122
- sel_attributes.delete(attr)
123
- end
124
- end
125
- end
126
- if @_excluded_attributes && !@_excluded_attributes.empty?
127
- @_excluded_attributes.each { |attr| sel_attributes.delete(attr) }
128
- end
129
- sel_attributes
130
- end
131
- else
132
- base.instance_exec do
133
- def attribute(name, options = {})
134
- indexed_attributes[name] = options.delete(:index) if options.key?(:index)
135
- attribute_conditions[name] = options
136
-
137
- define_method(name) do
138
- @_raw_attributes[name]
139
- end
140
-
141
- define_method("#{name}=") do |val|
142
- val = _validate_attribute(name, val)
143
- changed!
144
- @_raw_attributes[name] = val
145
- end
146
- end
147
- end
148
-
149
- def attributes
150
- @_raw_attributes
151
- end
152
-
153
- def _get_selected_attributes
154
- sel_attributes = attributes.transform_keys(&:to_s)
155
- self.class.attribute_conditions.each do |attr, options|
156
- sel_attributes.delete(attr.to_s) if options[:server_only]
157
- end
158
- if @_selected_attributes && !@_selected_attributes.empty?
159
- sel_attributes.each_key do |attr|
160
- unless @_selected_attributes.include?(attr.to_sym) || @_selected_attributes.include?(attr)
161
- sel_attributes.delete(attr)
162
- end
163
- end
164
- end
165
- if @_excluded_attributes && !@_excluded_attributes.empty?
166
- @_excluded_attributes.each { |attr| sel_attributes.delete(attr.to_s) }
167
- end
168
- sel_attributes
169
- end
170
- end
171
- end
172
- end
173
- end
174
- end