infopark_fiona7 1.2.0.0.1 → 1.2.0.1.1
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/scrivito_patches/models/obj.js +2 -6
- data/infopark_fiona7.gemspec +1 -1
- data/lib/fiona7/attribute_readers/attribute_reader.rb +17 -0
- data/lib/fiona7/attribute_readers/binary_as_binary.rb +12 -0
- data/lib/fiona7/attribute_readers/binary_as_linklist.rb +26 -0
- data/lib/fiona7/attribute_readers/date_as_date.rb +18 -0
- data/lib/fiona7/attribute_readers/factory.rb +91 -0
- data/lib/fiona7/attribute_readers/helpers/html_deserializer.rb +21 -0
- data/lib/fiona7/attribute_readers/helpers/json_deserializer.rb +11 -0
- data/lib/fiona7/attribute_readers/helpers/link_deserializer.rb +32 -0
- data/lib/fiona7/attribute_readers/html_as_html.rb +14 -0
- data/lib/fiona7/attribute_readers/link_as_linklist.rb +13 -0
- data/lib/fiona7/attribute_readers/linklist_as_linklist.rb +15 -0
- data/lib/fiona7/attribute_readers/multienum_as_multienum.rb +12 -0
- data/lib/fiona7/attribute_readers/multienum_as_text.rb +14 -0
- data/lib/fiona7/attribute_readers/number_as_string.rb +11 -0
- data/lib/fiona7/attribute_readers/reference_as_linklist.rb +14 -0
- data/lib/fiona7/attribute_readers/reference_as_string.rb +11 -0
- data/lib/fiona7/attribute_readers/referencelist_as_linklist.rb +16 -0
- data/lib/fiona7/attribute_readers/referencelist_as_text.rb +14 -0
- data/lib/fiona7/attribute_readers/simple.rb +18 -0
- data/lib/fiona7/attribute_readers/stringlist_as_text.rb +18 -0
- data/lib/fiona7/attribute_readers/widgetlist_as_linklist.rb +33 -0
- data/lib/fiona7/attribute_type_mapper.rb +76 -0
- data/lib/fiona7/attribute_writers/attribute_writer.rb +16 -0
- data/lib/fiona7/attribute_writers/binary_as_binary.rb +74 -0
- data/lib/fiona7/attribute_writers/binary_as_linklist.rb +86 -0
- data/lib/fiona7/attribute_writers/date_as_date.rb +11 -0
- data/lib/fiona7/attribute_writers/factory.rb +90 -0
- data/lib/fiona7/attribute_writers/helpers/html_serializer.rb +21 -0
- data/lib/fiona7/attribute_writers/helpers/json_serializer.rb +11 -0
- data/lib/fiona7/attribute_writers/helpers/link_serializer.rb +37 -0
- data/lib/fiona7/attribute_writers/html_as_html.rb +12 -0
- data/lib/fiona7/attribute_writers/link_as_linklist.rb +18 -0
- data/lib/fiona7/attribute_writers/linklist_as_linklist.rb +16 -0
- data/lib/fiona7/attribute_writers/multienum_as_multienum.rb +11 -0
- data/lib/fiona7/attribute_writers/multienum_as_text.rb +12 -0
- data/lib/fiona7/attribute_writers/number_as_string.rb +11 -0
- data/lib/fiona7/attribute_writers/reference_as_linklist.rb +17 -0
- data/lib/fiona7/attribute_writers/reference_as_string.rb +11 -0
- data/lib/fiona7/attribute_writers/referencelist_as_linklist.rb +19 -0
- data/lib/fiona7/attribute_writers/referencelist_as_text.rb +13 -0
- data/lib/fiona7/attribute_writers/simple.rb +11 -0
- data/lib/fiona7/attribute_writers/stringlist_as_text.rb +16 -0
- data/lib/fiona7/attribute_writers/widgetlist_as_linklist.rb +33 -0
- data/lib/fiona7/builder/obj_builder.rb +12 -201
- data/lib/fiona7/controllers/rest_api/obj_controller.rb +23 -5
- data/lib/fiona7/engine.rb +39 -0
- data/lib/fiona7/json/obj_decorator.rb +29 -121
- data/lib/fiona7/prefetch/obj_prefetch.rb +42 -0
- data/lib/fiona7/prefetch/widget_resolver_prefetch.rb +36 -0
- data/lib/fiona7/scrivito_patches/date_attribute.rb +16 -0
- data/lib/fiona7/tools/attribute_remover.rb +70 -0
- data/lib/fiona7/type_register.rb +9 -1
- data/lib/fiona7/version.rb +1 -1
- data/lib/fiona7/widget_resolver.rb +6 -6
- metadata +51 -4
@@ -15,6 +15,9 @@ require 'fiona7/assert'
|
|
15
15
|
require 'fiona7/json/reverse_obj_decorator'
|
16
16
|
require 'fiona7/json/typeless_obj_decorator'
|
17
17
|
|
18
|
+
require 'fiona7/prefetch/obj_prefetch'
|
19
|
+
require 'fiona7/prefetch/widget_resolver_prefetch'
|
20
|
+
|
18
21
|
module Fiona7
|
19
22
|
module Controllers
|
20
23
|
module RestAPI
|
@@ -61,10 +64,13 @@ module Fiona7
|
|
61
64
|
# FIXME: code duplication with fetch_by_id
|
62
65
|
obj_ids = payload.with_indifferent_access[:ids]
|
63
66
|
klass = revision_id.start_with?('f') ? ReleasedObj : EditedObj
|
64
|
-
objs = klass.where(obj_id: obj_ids)
|
65
|
-
objs_arr = obj_ids.map {|obj_id| objs.find {|o| o.id == obj_id.to_i } }
|
66
67
|
|
67
|
-
|
68
|
+
# preloads all objects in one query
|
69
|
+
objs_arr = Prefetch::ObjPrefetch.new(klass, obj_ids).find_many(obj_ids)
|
70
|
+
# preloads all widgets in one query
|
71
|
+
widget_prefetch = Prefetch::WidgetResolverPrefetch.new(klass, objs_arr.compact)
|
72
|
+
|
73
|
+
decorated = objs_arr.map {|obj| obj ? Fiona7::JSON::ReverseObjDecorator.new(klass, obj, widget_prefetch.widget_resolver(obj)) : nil }
|
68
74
|
response = ::JSON.parse(::ActiveSupport::JSON.encode({"results" => decorated}))
|
69
75
|
return response
|
70
76
|
end
|
@@ -112,11 +118,23 @@ module Fiona7
|
|
112
118
|
conti = {}
|
113
119
|
end
|
114
120
|
|
121
|
+
# This simulates the behavior of the backend:
|
122
|
+
# In absence of other input backend always sorts by ID
|
123
|
+
# or SCORE if an elastic search for such request would
|
124
|
+
# produce a score.
|
125
|
+
if (params[:query]||[]).any?{|op| (op[:operator]||op["operator"]).to_s =~ /search/ }
|
126
|
+
default_sort_order = :desc
|
127
|
+
default_sort_by = :_score
|
128
|
+
else
|
129
|
+
default_sort_order = :asc
|
130
|
+
default_sort_by = :id
|
131
|
+
end
|
132
|
+
|
115
133
|
offset = conti[:offset] || params[:offset] || 0
|
116
134
|
# 10 is the default value in original implementation
|
117
135
|
size = conti[:size] || params[:size] || 10
|
118
|
-
order = (conti[:sort_order] || params[:sort_order] ||
|
119
|
-
sort = (conti[:sort_by] || params[:sort_by] ||
|
136
|
+
order = (conti[:sort_order] || params[:sort_order] || default_sort_order).to_sym
|
137
|
+
sort = (conti[:sort_by] || params[:sort_by] || default_sort_by).to_sym
|
120
138
|
|
121
139
|
if params[:query].present?
|
122
140
|
normalize_query_params(params[:query])
|
data/lib/fiona7/engine.rb
CHANGED
@@ -59,6 +59,9 @@ require 'fiona7/type_synchronizer'
|
|
59
59
|
require 'fiona7/naive_search_engine'
|
60
60
|
require 'fiona7/verity_search_engine'
|
61
61
|
|
62
|
+
# tools
|
63
|
+
require 'fiona7/tools/attribute_remover'
|
64
|
+
|
62
65
|
module Fiona7
|
63
66
|
mattr_accessor :mode
|
64
67
|
mattr_accessor :login
|
@@ -71,6 +74,42 @@ module Fiona7
|
|
71
74
|
:release_obj => []
|
72
75
|
}
|
73
76
|
|
77
|
+
# Allows to specify custom typing for virtual attribute types
|
78
|
+
# Besides the built in mapping:
|
79
|
+
# link: :linklist,
|
80
|
+
# reference: :linklist,
|
81
|
+
# referencelist: :linklist,
|
82
|
+
# widgetlist: :linklist,
|
83
|
+
# binary: :linklist,
|
84
|
+
# number: :string,
|
85
|
+
# stringlist: :text
|
86
|
+
#
|
87
|
+
# Following other options are supported:
|
88
|
+
# reference: :string,
|
89
|
+
# referencelist: :text
|
90
|
+
#
|
91
|
+
# Custom mappings can be specified per obj_class:
|
92
|
+
#
|
93
|
+
# custom_attribute_types = {
|
94
|
+
# 'MyPage' => {
|
95
|
+
# child_order: :text
|
96
|
+
# }
|
97
|
+
# }
|
98
|
+
#
|
99
|
+
# or per attribute:
|
100
|
+
#
|
101
|
+
# custom_attribute_types = {
|
102
|
+
# child_order: :text
|
103
|
+
# }
|
104
|
+
#
|
105
|
+
# or using a callable entity like a proc:
|
106
|
+
#
|
107
|
+
# custom_attribute_types = lambda do |obj_class, attribute|
|
108
|
+
# :text if attribute == :child_order
|
109
|
+
# end
|
110
|
+
mattr_accessor :custom_attribute_types
|
111
|
+
self.custom_attribute_types = {}
|
112
|
+
|
74
113
|
mattr_accessor :search_engine
|
75
114
|
self.search_engine = Fiona7::VeritySearchEngine
|
76
115
|
|
@@ -6,10 +6,11 @@ module Fiona7
|
|
6
6
|
end
|
7
7
|
|
8
8
|
require 'fiona7/assert'
|
9
|
-
require 'fiona7/link_converter/fiona_to_scrivito'
|
10
9
|
require 'fiona7/json/widget_decorator'
|
11
10
|
require 'fiona7/widget_resolver'
|
12
|
-
require 'fiona7/
|
11
|
+
require 'fiona7/prefetch/obj_prefetch'
|
12
|
+
|
13
|
+
require 'fiona7/attribute_readers/factory'
|
13
14
|
|
14
15
|
module Fiona7
|
15
16
|
module JSON
|
@@ -18,12 +19,10 @@ module Fiona7
|
|
18
19
|
@klass = klass
|
19
20
|
@obj = obj
|
20
21
|
|
21
|
-
@link_converter = LinkConverter::FionaToScrivito.new(obj)
|
22
|
-
|
23
22
|
if widget_resolver
|
24
23
|
@widget_resolver = widget_resolver
|
25
24
|
elsif (widget_links = @obj.attr_values["X_widget_pool"])
|
26
|
-
@widget_resolver = WidgetResolver.new(widget_links,
|
25
|
+
@widget_resolver = WidgetResolver.new(widget_links, Prefetch::ObjPrefetch.new(klass))
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
@@ -58,137 +57,46 @@ module Fiona7
|
|
58
57
|
|
59
58
|
def add_custom_attributes(attrs, *args)
|
60
59
|
type_definition = Fiona7::TypeRegister.instance.read_mangled(@obj.obj_class)
|
60
|
+
factory = Fiona7::AttributeReaders::Factory.new(@obj, type_definition, @widget_resolver)
|
61
|
+
|
61
62
|
type_definition.attrs.each do |attribute|
|
62
63
|
virtual_attribute_name = attribute.name
|
63
64
|
real_attribute_name = attribute.real_name
|
64
65
|
virtual_attribute_type = attribute.type.to_sym
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
when :html
|
87
|
-
deserialize_html(@obj[real_attribute_name])
|
88
|
-
when :markdown
|
89
|
-
nil
|
90
|
-
when :binary
|
91
|
-
if !Fiona7.mode == :legacy || !@obj.binary?
|
92
|
-
deserialize_binary(@obj.attr_values[real_attribute_name].try(:first))
|
93
|
-
else
|
94
|
-
{id: Fiona7::BlobIdGenerator.new(@obj.id, @obj.last_changed).call}
|
95
|
-
end
|
96
|
-
when :enum, :multienum, :text, :string
|
97
|
-
if real_attribute_name == "suppress_export"
|
98
|
-
@obj[real_attribute_name].to_s
|
99
|
-
else
|
100
|
-
@obj[real_attribute_name]
|
101
|
-
end
|
102
|
-
when :number
|
103
|
-
@obj[real_attribute_name].to_f
|
104
|
-
when :stringlist
|
105
|
-
if Fiona7.mode == :legacy && real_attribute_name == "channels"
|
106
|
-
@obj["channels"] || []
|
107
|
-
else
|
108
|
-
# TODO: get rid of this rescue nil
|
109
|
-
::JSON.parse(@obj[real_attribute_name]) rescue nil
|
110
|
-
end
|
66
|
+
# This is probably the most important line in this whole class.
|
67
|
+
# An intuitive way of reading the real attribute type
|
68
|
+
# would be to just look-up in the attribute definition.
|
69
|
+
#
|
70
|
+
# But this approach is wrong. Consider the following case:
|
71
|
+
# An attribute :child_order is created with real type :linklist
|
72
|
+
# This proves problematic (because of the unwanted links in CMS)
|
73
|
+
# and is later changed to :text. But the CMS still contains
|
74
|
+
# "old" objects with :child_order modelled as :linklist.
|
75
|
+
# Therefore we must lookup the correct typing in the attribute itself.
|
76
|
+
#
|
77
|
+
# It is also possible that the obj does not have any content for the
|
78
|
+
# attribute. In this case we just use the type provided by
|
79
|
+
# the type definition.
|
80
|
+
real_attribute_type = ((@obj.attr_dict.send(:attr_defs) || {})[real_attribute_name.to_s]||{})["type"] ||
|
81
|
+
attribute.real_type
|
82
|
+
|
83
|
+
worker = factory.call(real_attribute_name, virtual_attribute_type, real_attribute_type)
|
84
|
+
if worker.nil?
|
85
|
+
Rails.logger.error("Unable to deserialize #{virtual_attribute_name} in #{type_definition.name}")
|
86
|
+
val = nil
|
111
87
|
else
|
112
|
-
|
113
|
-
false,
|
114
|
-
"Unknown attribute type #{virtual_attribute_type} for attribute: #{virtual_attribute_name}"
|
115
|
-
)
|
88
|
+
val = worker.call
|
116
89
|
end
|
117
90
|
|
118
91
|
# TODO: better handling for attribute types
|
119
92
|
if virtual_attribute_type == :text
|
120
93
|
virtual_attribute_type = :string
|
121
94
|
end
|
122
|
-
attrs[virtual_attribute_name] = [val, virtual_attribute_type]
|
123
|
-
end
|
124
|
-
end
|
125
95
|
|
126
|
-
|
127
|
-
if link
|
128
|
-
deserialized = {
|
129
|
-
# remove possible external prefix for protcol-less urls
|
130
|
-
url: link["url"].try(:gsub, /\Aexternal:/, ''),
|
131
|
-
title: link["title"],
|
132
|
-
target: link["target"],
|
133
|
-
# content service uses destination
|
134
|
-
destination: link["destination"].to_s,
|
135
|
-
# rest api uses obj_id
|
136
|
-
obj_id: link["destination"].to_s,
|
137
|
-
query: link["search"],
|
138
|
-
fragment: link["fragment"]
|
139
|
-
}
|
140
|
-
|
141
|
-
# TODO: refactor this code
|
142
|
-
if deserialized[:url].present?
|
143
|
-
deserialized.delete(:destination)
|
144
|
-
deserialized.delete(:obj_id)
|
145
|
-
end
|
146
|
-
|
147
|
-
deserialized
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def deserialize_reference(link)
|
152
|
-
if link && link["type"] == "internal"
|
153
|
-
link["destination"].to_s
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def deserialize_widget_field(linklist)
|
158
|
-
if !linklist.empty?
|
159
|
-
widget_ids = []
|
160
|
-
widgets = linklist.map do |link|
|
161
|
-
widget_id = link["title"]
|
162
|
-
# sometimes a released page references an unreleased widget
|
163
|
-
# it is then impossible to load it into widget_pool
|
164
|
-
# but the reference in the widgetlist field is still there
|
165
|
-
# therefore we need to check if the widget has been loaded
|
166
|
-
# into the pool - only then it can be included
|
167
|
-
if valid_widget_id?(widget_id)
|
168
|
-
widget_ids << widget_id
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
widget_ids
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
def deserialize_html(html)
|
177
|
-
@link_converter.convert(html)
|
178
|
-
end
|
179
|
-
|
180
|
-
def deserialize_binary(link)
|
181
|
-
if link
|
182
|
-
binary_id = link["title"]
|
183
|
-
if binary_id.length == 32 && binary_id =~ /0{16,}0*[0-9]+/
|
184
|
-
{id: binary_id}
|
185
|
-
end
|
96
|
+
attrs[virtual_attribute_name] = [val, virtual_attribute_type]
|
186
97
|
end
|
187
98
|
end
|
188
99
|
|
189
|
-
def valid_widget_id?(widget_id)
|
190
|
-
@widget_resolver && @widget_resolver.path_map[widget_id]
|
191
|
-
end
|
192
100
|
|
193
101
|
def replace_widget_pool(attrs, *args)
|
194
102
|
if (widget_links = @obj.attr_values["X_widget_pool"]) && @widget_resolver
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Fiona7
|
4
|
+
module Prefetch
|
5
|
+
class ObjPrefetch
|
6
|
+
def initialize(klass, prefetch_ids=[])
|
7
|
+
self.klass = klass
|
8
|
+
self.prefetched_ids = Set.new
|
9
|
+
self.object_id_map = {}
|
10
|
+
|
11
|
+
self.prefetch_objects(prefetch_ids)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns an object with given ID or nil if no matching object found
|
15
|
+
def find_one(id)
|
16
|
+
self.find_many([id]).first
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an array with objects for given IDs.
|
20
|
+
# The array is ordered according to the IDs given.
|
21
|
+
# For missing objects the array is filled with nil values
|
22
|
+
def find_many(ids)
|
23
|
+
self.prefetch_objects(ids)
|
24
|
+
ids.map { |id| self.object_id_map[id.to_i] }
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
attr_accessor :klass, :prefetched_ids, :object_id_map
|
29
|
+
|
30
|
+
def prefetch_objects(prefetch_ids)
|
31
|
+
missing = prefetch_ids.select {|id| !self.prefetched_ids.include?(id) }
|
32
|
+
|
33
|
+
return if missing.empty?
|
34
|
+
|
35
|
+
self.klass.where(obj_id: missing).each do |obj|
|
36
|
+
self.prefetched_ids << obj.id
|
37
|
+
self.object_id_map[obj.id] = obj
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fiona7/prefetch/obj_prefetch'
|
2
|
+
require 'fiona7/widget_resolver'
|
3
|
+
|
4
|
+
module Fiona7
|
5
|
+
module Prefetch
|
6
|
+
class WidgetResolverPrefetch
|
7
|
+
def initialize(klass, objects=[])
|
8
|
+
widget_object_ids = self.collect_widget_object_ids(objects)
|
9
|
+
|
10
|
+
self.obj_prefetch = ObjPrefetch.new(klass, widget_object_ids)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns a widget resolver for given object.
|
14
|
+
# If the object is already known to the prefetcher,
|
15
|
+
# then widgets will be loaded from memory,
|
16
|
+
# instead of database.
|
17
|
+
def widget_resolver(object)
|
18
|
+
WidgetResolver.new(
|
19
|
+
object.attr_values["X_widget_pool"]||[],
|
20
|
+
self.obj_prefetch
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
attr_accessor :obj_prefetch
|
26
|
+
|
27
|
+
def collect_widget_object_ids(objects)
|
28
|
+
objects.map do |object|
|
29
|
+
(object.attr_values["X_widget_pool"]||[]).map do |widget_hash|
|
30
|
+
widget_hash["destination"].try(:to_i)
|
31
|
+
end
|
32
|
+
end.flatten.compact
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'scrivito/date_attribute'
|
2
|
+
|
3
|
+
module Scrivito
|
4
|
+
module DateAttribute
|
5
|
+
def self.deserialize_from_backend(iso_date_time)
|
6
|
+
return nil unless iso_date_time
|
7
|
+
#return nil if iso_date.to_s.blank?
|
8
|
+
|
9
|
+
if iso_date_time.to_s =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/
|
10
|
+
Time.utc($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i).in_time_zone
|
11
|
+
else
|
12
|
+
raise "The value is not a valid ISO date time: #{iso_date_time.inspect}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'fiona7/obj_class_name_mangler'
|
2
|
+
require 'fiona7/attribute_name_mangler'
|
3
|
+
|
4
|
+
module Fiona7
|
5
|
+
module Tools
|
6
|
+
# This class is used to remove attributes from obj classes.
|
7
|
+
# Normally it is not required, because the user can just
|
8
|
+
# remove an attribute from the model definition and the
|
9
|
+
# attribute becomes invisible.
|
10
|
+
# The attribute still persists, but becomes inaccessible.
|
11
|
+
#
|
12
|
+
# In some cases it may be required to garbage collect
|
13
|
+
# the removed attribute, for example to change the type
|
14
|
+
# of an attribute, the attribute has to be removed first.
|
15
|
+
#
|
16
|
+
# This class behaves differently for different configrations.
|
17
|
+
# In standalone mode the attribute is removed from
|
18
|
+
# the specified obj class and also from CMS.
|
19
|
+
# In legacy mode the attribute is removed from
|
20
|
+
# the specified obj class. If there are no more obj classes
|
21
|
+
# referencing this attribute, it also gets deleted from CMS.
|
22
|
+
class AttributeRemover
|
23
|
+
def initialize(obj_class, attr_name)
|
24
|
+
self.obj_class = ObjClassNameMangler.new(obj_class).mangle
|
25
|
+
self.attr_name = AttributeNameMangler.new(attr_name, obj_class).mangle
|
26
|
+
|
27
|
+
self.original_attr_name = attr_name
|
28
|
+
self.original_obj_class = obj_class
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove
|
32
|
+
if rc_attr = RailsConnector::Attribute.find_by_attribute_name(self.attr_name)
|
33
|
+
# fetch the names of all obj classes referencing this attribute
|
34
|
+
obj_classes = rc_attr.obj_class_defs.map(&:name)
|
35
|
+
if obj_classes.include?(self.obj_class)
|
36
|
+
cm_obj_class = Reactor::Cm::ObjClass.get(self.obj_class)
|
37
|
+
# this removes the attribute from the obj class
|
38
|
+
cm_obj_class.attributes = (cm_obj_class.attributes - [self.attr_name])
|
39
|
+
# flush reactor cache
|
40
|
+
RailsConnector::Meta::EagerLoader.instance.forget_obj_class(self.obj_class)
|
41
|
+
# flush type register caches
|
42
|
+
Fiona7::TypeRegister.instance.send(:load, self.original_obj_class)
|
43
|
+
if typedef = Fiona7::TypeRegister.instance.usr_defs[self.original_obj_class]
|
44
|
+
# There is a very subtle bug hidden here:
|
45
|
+
# If you have an enum or multienum attribute, remove it and
|
46
|
+
# trigger synchronize (via write request) it will be created
|
47
|
+
# as string or text.
|
48
|
+
#
|
49
|
+
# Easiest way to prevent this bug is to restart the app
|
50
|
+
# between the requests.
|
51
|
+
typedef.remove_attribute(self.original_attr_name)
|
52
|
+
end
|
53
|
+
# one reference less!
|
54
|
+
obj_classes.delete(self.obj_class)
|
55
|
+
end
|
56
|
+
|
57
|
+
# NOTE: this will always be true in standlone mode
|
58
|
+
if obj_classes.empty?
|
59
|
+
# attribute can be garbage collected
|
60
|
+
cm_attr = Reactor::Cm::Attribute.get(self.attr_name)
|
61
|
+
cm_attr.delete!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
attr_accessor :obj_class, :attr_name, :original_obj_class, :original_attr_name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|