module PIM::Validations
Constants
- DEFAULT_CONTEXT_VARIABLE_NAME
Public Instance Methods
all_rules_by_attribute(attribute, *tags)
click to toggle source
# File pim.rb, line 7681 def all_rules_by_attribute attribute, *tags rule_names = [] rule_names.concat(@module_rules_by_attribute[attribute]) if @module_rules_by_attribute add_parent_objects(rule_names) { |p| p.module_rules_by_attribute[attribute] } rule_names.empty? ? {} : filter_rules_by_tags(all_rules_by_names(*rule_names), *tags) end
all_rules_by_dependent_attribute(attribute, *tags)
click to toggle source
# File pim.rb, line 7688 def all_rules_by_dependent_attribute attribute, *tags rule_names = [] rule_names.concat(@module_rules_by_dependent_attribute[attribute]) if @module_rules_by_dependent_attribute add_parent_objects(rule_names) { |p| p.module_rules_by_dependent_attribute[attribute] } rule_names.empty? ? {} : filter_rules_by_tags(all_rules_by_names(*rule_names), *tags) end
all_rules_by_names(*names)
click to toggle source
# File pim.rb, line 7708 def all_rules_by_names *names rules = {} rules.merge!(module_rules_by_names(*names)) add_parent_objects(rules) { |p| p.module_rules_by_names(*names) } rules end
all_rules_by_params(*params)
click to toggle source
# File pim.rb, line 7701 def all_rules_by_params *params rules = {} rules.merge!(module_rules_by_params(*params)) add_parent_objects(rules) { |p| p.module_rules_by_params(*params) } rules end
attribute_rule(name, *attributes, &block)
click to toggle source
# File pim.rb, line 7670 def attribute_rule name, *attributes, &block raise "No attributes specified for rule '#{name}'" if attributes.empty? validation name, *attributes, &block end
create_validation_rule(validation_rule_hash)
click to toggle source
# File pim.rb, line 7635 def create_validation_rule validation_rule_hash name = PIM.get_value(validation_rule_hash, :name).to_sym attributes = PIM.get_value(validation_rule_hash, :validated_attributes, :attributes) dependent_attributes = PIM.get_value(validation_rule_hash, :dependent_attributes) tags = PIM.get_value(validation_rule_hash, :tags) disabled_block = PIM.get_value(validation_rule_hash, :disabled_block) validation_block = PIM.get_value(validation_rule_hash, :validation_block) # Create validation_block, unless specified if validation_block.nil? context_variable_name = PIM.get_value(validation_rule_hash, :ruby_code_context_variable_name) || DEFAULT_CONTEXT_VARIABLE_NAME ruby_code = PIM.get_value(validation_rule_hash, :ruby_code) raise "Neither validation block nor ruby code specified for validation rule '#{name}'" if ruby_code.nil? validation_block = eval("proc { |#{context_variable_name}| #{ruby_code} }") end opts = { attributes: attributes, dependent_attributes: dependent_attributes, tags: tags, disabled_block: disabled_block } validation_rule = PIM::ValidationRule.new(name, opts, &validation_block) add_validation_rule validation_rule validation_rule end
exists_validation_rule?(validation_rule)
click to toggle source
# File pim.rb, line 7631 def exists_validation_rule? validation_rule validation_rule and all_rules_by_names.has_key?(to_sym(validation_rule)) end
key_location(key_hash)
click to toggle source
# File pim.rb, line 7961 def key_location key_hash result = "" key_hash.each_pair do |k, v| next if !v attribute = attribute(k) label = attribute.label result << ", " unless result.empty? result << label << " " << "'" << v.to_s << "'" end result end
location_msg(path)
click to toggle source
# File pim.rb, line 7927 def location_msg path if path.length > 1 child_attribute = attribute(path.last) label = child_attribute.label location_msg = "In attribute '#{label}'" if path.length > 2 parent_attribute = attribute(path.first) path_index = path[1] if parent_attribute.base_class == Array index = path_index.to_i location_msg << ", row #{index+1}" elsif parent_attribute.base_class == Hash key = path_index.to_s location_msg << ", key '#{key}'" elsif is_hash?(path_index) key_location = key_location(path_index) location_msg << ", #{key_location}" end end location_msg << ": " else "" end end
module_rules_by_attribute()
click to toggle source
# File pim.rb, line 7977 def module_rules_by_attribute @module_rules_by_attribute ||= Hash.new { |k,v| k[v] = [] } end
module_rules_by_dependent_attribute()
click to toggle source
# File pim.rb, line 7981 def module_rules_by_dependent_attribute @module_rules_by_dependent_attribute ||= Hash.new { |k,v| k[v] = [] } end
module_rules_by_name()
click to toggle source
# File pim.rb, line 8007 def module_rules_by_name @module_rules_by_name ||= {} end
module_rules_by_names(*names)
click to toggle source
# File pim.rb, line 7998 def module_rules_by_names *names if @module_rules_by_name rules = @module_rules_by_name.select { |k,v| names.empty? or names.include?(k) } else rules = {} end rules end
module_rules_by_param()
click to toggle source
# File pim.rb, line 7994 def module_rules_by_param @module_rules_by_param ||= {} end
module_rules_by_params(*params)
click to toggle source
# File pim.rb, line 7985 def module_rules_by_params *params if @module_rules_by_param rules = @module_rules_by_param.select { |k,v| params.empty? or params.include?(k) } else rules = {} end rules end
param_rule(name, &block)
click to toggle source
# File pim.rb, line 7675 def param_rule name, &block raise "Validation rule for parameter '#{name}' is already defined" if module_rules_by_param.has_key?(name) rule = PIM::ValidationRule.new(name, &block) module_rules_by_param[name] = rule end
validate(old_item, new_item, *attributes)
click to toggle source
# File pim.rb, line 7820 def validate old_item, new_item, *attributes PIM::Utils.timed(group: "validation", key: "validate-initialize", message: "Initialization point 'validation'") do initialization_point :validation end if has_initialization_point?(:validation) # Copy input values old_item = symbolized_hash(old_item) if old_item new_item = symbolized_hash(new_item) if new_item attributes = symbolized_array(attributes || []).sort result = PIM::ValidationResult.new # Determine the item's category category_value = (new_item[:category__]) if new_item if !category_value message = "The item does not have a category specified" if not data_module.has_option?(:ignore_no_category) result.fail PIM::ValidationRule.new(:no_category), PIM::ValidationLevel::ERROR, [:category__], message else PIM.log_debug(message) end category = nil else # Check if category exists category = category(category_value) if !category message = "The item's category '#{category_value}' is not defined in the data model" params = { :err_val => category_value } result.fail PIM::ValidationRule.new(:undefined_category), PIM::ValidationLevel::ERROR, [:category__], message, params end end # FIXME: No category and no attribute to validate => Validate all attributes in item # No category and no attributes specified => Nothing to do here if !category && is_empty?(attributes) return result end context = { category: category, old_values: old_item, unparsed_values: new_item, parsed_values: {}, attributes: {}, cache: {}, additional_attribute_categories: {}, parsed_attributes: Set.new(), updated_attributes: Set.new(attributes.sort), undefined_attributes: Set.new(attributes.sort) } # 'Super' hash to return parsed value or ensure value gets parsed first context[:values] = Hash.new do |hash, key| key = PIM.to_sym(key) # Ensure value is parsed parsed_values = context[:parsed_values] if parsed_values.key?(key) value = parsed_values[key] else if parse_attribute_value(result, key, context, check_regular: false) value = parsed_values[key] end end value end # Determine tags of service validations to load and apply depending on category unless category.nil? validation_tags_context = PIM::ValidationTagsContext.new(self, result, context) validation_tags = category.calculate_validation_tags(validation_tags_context) context[:validation_tags] = validation_tags unless validation_tags.nil? or validation_tags.empty? end PIM::Utils.timed(group: "validation", key: "execute_module_validation-#{data_module}", message: "Execute full validation on data module #{data_module}") do execute_module_validation result, data_module, context end # Add validation error for all "undefined" attributes, i.e. attributes not defined in any data model! undefined_attributes = context[:undefined_attributes] undefined_attributes.sort.each do |attribute_name| next if is_meta_attribute?(attribute_name) message = "Attribute '#{attribute_name}' is not defined in module '#{data_module.name}' and will not be validated" if not data_module.has_option?(:ignore_undefined_attributes) params = { :err_val => attribute_name } result.fail PIM::ValidationRule.new(:undefined_attribute), PIM::ValidationLevel::ERROR, [attribute_name], message, params else PIM.log_debug(message) end end return result end
validate_items(*items)
click to toggle source
# File pim.rb, line 7715 def validate_items *items validation_results = [] return validation_results if items.empty? PIM::Utils.timed(group: "validation", key: "validate-initialize", message: "Initialization point 'validation'") do initialization_point :validation end if has_initialization_point?(:validation) # Get json item cache and ensure the size is big enough for a reasonable number of more items item_cache = data_module.item_cache(type: :json) item_cache.min_size = items.length * 1.5 # Ensure items are in a proper JSON format, i.e. NOT symbolize items = items.map { |item| PIM.unsymbolized_hash(item) } # Add all items to local cache item_primary_keys = Set.new items.each do |item| primary_key = get_value(item, :primaryKey__) unless primary_key.nil? item_primary_keys << primary_key item_cache[primary_key] = item end end # Check if more items should be pre-loaded if data_module.has_option?(:preload_referenced_items) # Ensure cache is big enough max_number_of_items = data_module.get_option(:preload_referenced_items_size, PIM::DataModel::PRELOAD_REFERENCED_ITEMS_DEFAULT_SIZE) max_number_of_items = max_number_of_items.clamp(0, PIM::DataModel::PRELOAD_REFERENCED_ITEMS_MAX_SIZE) item_cache.min_size = (items.length * 1.5) + max_number_of_items # Set format to preload items in item_format = data_module.get_option(:preload_referenced_items_format, :json) # Load queried items ONLY if format is NOT json, because json items are already loaded and cached! load_queried_items = item_format.to_s != 'json' # Preload referenced items for specified or all hierarchies hierarchy_names = data_module.get_option(:preload_referenced_items_hierarchy_names, nil) preloaded_items = PIM::Services::ItemService.get_items_referenced_by_item_hierarchies(*item_primary_keys, format: item_format, hierarchy_names: hierarchy_names, load_queried_items: load_queried_items, max_number_of_items: max_number_of_items) PIM.log_debug "Preloaded #{preloaded_items.size} #{item_format} item(s) into cache" end items.each do |item| # Validate item validation_result = validate(item, item) validation_results << validation_result # Set attribute states attribute_states = [] validation_result.states_by_attribute_name.each_pair do |attribute, states| states.each do |state| attribute_states << "#{attribute}:#{state}" end end item['attributeStates__'] = attribute_states # Set validation errors and warnings validation_errors = [] validation_warnings = [] validation_result.messages_by_attribute_name.each_pair do |attribute, messages| messages.each do |message| validation = "#{attribute}:#{message.name}" if message.level == ValidationLevel::ERROR or message.level == ValidationLevel::FAILURE validation_errors << validation elsif message.level == ValidationLevel::WARNING validation_warnings << validation end end end item['validation__'] = validation_errors item['validation_warnings__'] = validation_warnings # Set calculated values validation_result.calculated_values_by_attribute_name.each do |attribute, value| item[attribute.to_s] = PIM::Utils.as_json(value) end # Update other item validation system properties # NOTE: We are NOT updating checksum__, updatedAt__, updatedBy__, validatedAt__ or history__! item['validation_dirty__'] = false item['compliant__'] = PIM.is_empty?(item['validation__']) # Update item in local cache primary_key = item['primaryKey__'] item_cache[primary_key] = item unless primary_key.nil? end return validation_results end
validation(name, *attributes, &block)
click to toggle source
# File pim.rb, line 7612 def validation name, *attributes, &block name = to_sym(name) if not block.nil? validation_rule = PIM::ValidationRuleBuilder.build_validation_rule(data_module, name, *attributes, &block) add_validation_rule validation_rule elsif not attributes.empty? raise "No block specified for validation rule '#{name}'" else validation_rule = all_rules_by_names(name).first end validation_rule end
Also aliased as: validation_rule