lib/cocina/models/validators/description_values_validator.rb in cocina-models-0.94.2 vs lib/cocina/models/validators/description_values_validator.rb in cocina-models-0.95.0
- old
+ new
@@ -12,32 +12,35 @@
def initialize(clazz, attributes)
@clazz = clazz
@attributes = attributes
@error_paths_multiple = []
@error_paths_blank = []
+ @error_paths_missing_title_type = []
end
def validate
return unless meets_preconditions?
validate_obj(attributes, [])
raise ValidationError, "Multiple value, groupedValue, structuredValue, and parallelValue in description: #{error_paths_multiple.join(', ')}" unless error_paths_multiple.empty?
raise ValidationError, "Blank value in description: #{error_paths_blank.join(', ')}" unless error_paths_blank.empty?
+ raise ValidationError, "Missing type for value in description: #{error_paths_missing_title_type.join(', ')}" unless error_paths_missing_title_type.empty?
end
private
- attr_reader :clazz, :attributes, :error_paths_blank, :error_paths_multiple
+ attr_reader :clazz, :attributes, :error_paths_blank, :error_paths_multiple, :error_paths_missing_title_type
def meets_preconditions?
[Cocina::Models::Description, Cocina::Models::RequestDescription].include?(clazz)
end
def validate_hash(hash, path)
validate_values_for_blanks(hash, path)
validate_values_for_multiples(hash, path)
+ validate_title_type(hash, path)
hash.each do |key, obj|
validate_obj(obj, path + [key])
end
end
@@ -60,9 +63,22 @@
def validate_values_for_multiples(hash, path)
return unless hash.count { |key, value| %i[value groupedValue structuredValue parallelValue].include?(key) && value.present? } > 1
error_paths_multiple << path_to_s(path)
+ end
+
+ def validate_title_type(hash, path)
+ # only apply to title.structuredValue, title.parallelValue.structuredValue, or relatedResource.title with a value
+ return unless hash[:value] && (path.first == :title || related_resource_title?(path)) && path.include?(:structuredValue)
+
+ # if there is a "value" key, make sure there is also a "type" key, only for title.structuredValue
+ error_paths_missing_title_type << path_to_s(path) unless hash[:type]
+ end
+
+ def related_resource_title?(path)
+ # title is directly within relatedResource, e.g [:relatedResource, 0, :title, 0, :structuredValue, 0])
+ path.first == :relatedResource && path[2] == :title
end
def path_to_s(path)
# This matches the format used by descriptive spreadsheets
path_str = ''