Class: Fiona7::Tools::AttributeRemover

Inherits:
Object
  • Object
show all
Defined in:
lib/fiona7/tools/attribute_remover.rb

Overview

This class is used to remove attributes from obj classes. Normally it is not required, because the user can just remove an attribute from the model definition and the attribute becomes invisible. The attribute still persists, but becomes inaccessible.

In some cases it may be required to garbage collect the removed attribute, for example to change the type of an attribute, the attribute has to be removed first.

This class behaves differently for different configrations. In standalone mode the attribute is removed from the specified obj class and also from CMS. In legacy mode the attribute is removed from the specified obj class. If there are no more obj classes referencing this attribute, it also gets deleted from CMS.

Instance Method Summary collapse

Constructor Details

#initialize(obj_class, attr_name) ⇒ AttributeRemover

Returns a new instance of AttributeRemover.



23
24
25
26
27
28
29
# File 'lib/fiona7/tools/attribute_remover.rb', line 23

def initialize(obj_class, attr_name)
  self.obj_class = ObjClassNameMangler.new(obj_class).mangle
  self.attr_name = AttributeNameMangler.new(attr_name, obj_class).mangle

  self.original_attr_name = attr_name
  self.original_obj_class = obj_class
end

Instance Method Details

#removeObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/fiona7/tools/attribute_remover.rb', line 31

def remove
  if rc_attr = RailsConnector::Attribute.find_by_attribute_name(self.attr_name)
    # fetch the names of all obj classes referencing this attribute
    obj_classes = rc_attr.obj_class_defs.map(&:name)
    if obj_classes.include?(self.obj_class)
      cm_obj_class = Reactor::Cm::ObjClass.get(self.obj_class)
      # this removes the attribute from the obj class
      cm_obj_class.attributes = (cm_obj_class.attributes - [self.attr_name])
      # flush reactor cache
      RailsConnector::Meta::EagerLoader.instance.forget_obj_class(self.obj_class)
      # flush type register caches
      Fiona7::TypeRegister.instance.send(:load, self.original_obj_class)
      if typedef = Fiona7::TypeRegister.instance.usr_defs[self.original_obj_class]
        # There is a very subtle bug hidden here:
        # If you have an enum or multienum attribute, remove it and
        # trigger synchronize (via write request) it will be created
        # as string or text.
        #
        # Easiest way to prevent this bug is to restart the app
        # between the requests.
        typedef.remove_attribute(self.original_attr_name)
      end
      # one reference less!
      obj_classes.delete(self.obj_class)
    end

    # NOTE: this will always be true in standlone mode
    if obj_classes.empty?
      # attribute can be garbage collected
      cm_attr = Reactor::Cm::Attribute.get(self.attr_name)
      cm_attr.delete!
    end
  end
end