Module: CocinaDisplay::Utils

Defined in:
lib/cocina_display/utils.rb

Overview

Helper methods for string formatting, etc.

Class Method Summary collapse

Class Method Details

.compact_and_join(values, delimiter: " ") ⇒ String

Join non-empty values into a string using provided delimiter. If values already end in delimiter (ignoring whitespace), join with a space instead.

Parameters:

  • values (Array<String>)

    The values to compact and join

  • delimiter (String) (defaults to: " ")

    The delimiter to use for joining, default is space

Returns:

  • (String)

    The compacted and joined string



11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/cocina_display/utils.rb', line 11

def self.compact_and_join(values, delimiter: " ")
  compacted_values = values.compact_blank.map(&:strip)
  return compacted_values.first if compacted_values.one?

  compacted_values.reduce(+"") do |result, value|
    result << if value.end_with?(delimiter.strip)
      value + " "
    else
      value + delimiter
    end
  end.delete_suffix(delimiter)
end

.deep_compact_blank(node, output = {}) ⇒ Hash

Recursively remove empty values from a hash, including nested hashes and arrays.

Examples:

hash = { "name" => "", "age" => nil, "address => { "city" => "Anytown", "state" => [] } }
#  Utils.remove_empty_values(hash)
#=> { "address" => { "city" => "Anytown" } }

Parameters:

  • hash (Hash)

    The hash to process

  • output (Hash) (defaults to: {})

    Used for recursion, should be empty on first call

Returns:

  • (Hash)

    The hash with empty values removed



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/cocina_display/utils.rb', line 61

def self.deep_compact_blank(node, output = {})
  return node unless node.is_a?(Hash)

  node.each do |key, value|
    if value.is_a?(Hash)
      nested = deep_compact_blank(value)
      output[key] = nested unless nested.empty?
    elsif value.is_a?(Array)
      compacted_array = value.map { |v| deep_compact_blank(v) }.reject(&:blank?)
      output[key] = compacted_array unless compacted_array.empty?
    elsif value.present?
      output[key] = value
    end
  end

  output
end

.flatten_nested_values(cocina, output = [], atomic_types: []) ⇒ Array<Hash>

Recursively flatten structured, and grouped values in Cocina metadata. Returns a list of hashes representing the “leaf” nodes with value key.

Examples:

simple value

cocina = { "value" => "John Doe", "type" => "name" }
Utils.flatten_nested_values(cocina)
#=> [{"value" => "John Doe", "type" => "name"}]

structured values

cocina = { "structuredValue" => [{"value" => "foo"},  {"value" => "bar"}] }
Utils.flatten_nested_values(cocina)
#=> [{"value" => "foo"}, {"value" => "bar"}]

nested structured and simple values

cocina = { "structuredValue" => [{"value" => "foo" }, { "structuredValue" => [{"value" => "bar"},  {"value" => "baz"}] }] }
Utils.flatten_nested_values(cocina)
#=> [{"value" => "foo"}, {"value" => "foo"}, {"value" => "baz"}]

Parameters:

  • cocina (Hash)

    The Cocina structured data to flatten

  • output (Array) (defaults to: [])

    Used for recursion, should be empty on first call

  • atomic_types (Array<String>) (defaults to: [])

    Types considered atomic; will not be flattened

Returns:

  • (Array<Hash>)

    List of node hashes with “value” present



42
43
44
45
46
47
48
49
50
51
# File 'lib/cocina_display/utils.rb', line 42

def self.flatten_nested_values(cocina, output = [], atomic_types: [])
  return [cocina] if cocina["value"].present?
  return [cocina] if atomic_types.include?(cocina["type"])
  return cocina.flat_map { |node| flatten_nested_values(node, output, atomic_types: atomic_types) } if cocina.is_a?(Array)

  nested_values = Array(cocina["structuredValue"]) + Array(cocina["groupedValue"])
  return output unless nested_values.any?

  nested_values.flat_map { |node| flatten_nested_values(node, output, atomic_types: atomic_types) }
end