require 'fiona7/assert' require 'fiona7/attribute_type_mapper' require 'fiona7/obj_class_name_demangler' module Fiona7 module Builder class ObjClassBuilder def initialize(values) @values = values @attributes = @values.delete(:attributes) {|_| [] } end def build assert_valid persist_attributes persist_obj_class end def validate unique_obj_class end protected def assert_valid validate || (raise (@error_msg || "Invalid input")) end def unique_obj_class ret = @values[:name].present? && !RailsConnector::ObjClass.exists?(obj_class_name: @values[:name]) @error_msg = "Expected the ObjClass not to exist: #{@values[:name]}" unless ret ret end def persist_attributes @attributes.each do |attribute| if !RailsConnector::Attribute.exists?(attribute_name: attribute[:real_name]) raw_attribute = Reactor::Cm::Attribute.create(attribute[:real_name].to_s, attribute[:real_type].to_s) raw_attribute.set(:helpText, ::ActiveSupport::JSON.encode({type: attribute[:type]})) raw_attribute.set(:values, attribute[:values]) if attribute[:values] raw_attribute.save! else cms_attribute = RailsConnector::Attribute.find_by_attribute_name(attribute[:real_name]) raw_attribute = Reactor::Cm::Attribute.get(attribute[:real_name].to_s) expected_real_type = Fiona7::AttributeTypeMapper.new( Fiona7::ObjClassNameDemangler.new(@values[:name]).demangle ).call(attribute[:name].to_sym, attribute[:type].to_sym) if attribute[:type] == :reference || attribute[:type] == :referencelist || attribute[:type] == :link || attribute[:type] == :widgetlist if cms_attribute.attribute_type == expected_real_type.to_s # FIXME: it is not neccessary to write this information for each sync raw_attribute.set(:helpText, ::ActiveSupport::JSON.encode({type: attribute[:type]})) raw_attribute.save! else Assert.constraint(false, "Type #{attribute[:type]} requested for #{attribute[:real_name]}, but is #{cms_attribute.attribute_type}") end elsif cms_attribute.attribute_type == "multienum" && attribute[:type] == :stringlist # This is a bit of hack. This allows a multienum to exist # But be treated in the application like a stringlist # # The intention here is to allow dynamically restricting or allowing # values in the application, while having a fixed superset of allowed # values in the CMS # # Nothing to do. Rails.logger.warn("TYPE SYNCHRONIZATION: Type #{attribute[:type]} requested for #{attribute[:real_name]}, but is #{cms_attribute.attribute_type}, this may cause errors.") elsif cms_attribute.attribute_type == "enum" && attribute[:type] == :string # This is a bit of hack. This allows an enum to exist # But be treated in the application like a string # # The intention here is to allow dynamically restricting or allowing # values in the application, while having a fixed superset of allowed # values in the CMS # # Nothing to do. Rails.logger.warn("TYPE SYNCHRONIZATION: Type #{attribute[:type]} requested for #{attribute[:real_name]}, but is #{cms_attribute.attribute_type}, this may cause errors.") elsif attribute[:type] == :enum || attribute[:type] == :multienum # TODO: AttributeTypeMapper if cms_attribute.attribute_type == "multienum" || cms_attribute.attribute_type == "enum" if attribute[:values] # do not remove values values = cms_attribute.values + attribute[:values] raw_attribute.set(:values, values) raw_attribute.save! end else if !((attribute[:type] == :enum && cms_attribute.attribute_type == "string") || (attribute[:type] == :multienum && cms_attribute.attribute_type == "text")) Assert.constraint(false, "Type #{attribute[:type]} requested for #{attribute[:real_name]}, but is #{cms_attribute.attribute_type}") end end elsif attribute[:real_type].to_s != expected_real_type.to_s Assert.constraint(false, "Type #{attribute[:type]} requested for #{attribute[:real_name]}, but is #{cms_attribute.attribute_type}") end end end end def persist_obj_class @values[:type] ||= 'publication' @raw_obj_class = Reactor::Cm::ObjClass.create(@values[:name].to_s, @values[:type].to_s) user_attributes = @attributes.map {|a| a[:real_name] } user_attributes ||= [] built_in_attributes = Fiona7::Initializer::ATTRIBUTES_MAP.keys @raw_obj_class.attributes = user_attributes + built_in_attributes end end end end