Class: Aspera::DotContainer

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/dot_container.rb

Overview

Convert dotted-path to/from nested Hash/Array container

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(container) ⇒ DotContainer

Returns a new instance of DotContainer.

Parameters:

  • Container (Hash, Array)

    object



51
52
53
54
55
56
# File 'lib/aspera/dot_container.rb', line 51

def initialize(container)
  Aspera.assert_type(container, Hash)
  # tail (pop,push) contains the next element to display
  # elements are [path, value]
  @stack = container.empty? ? [] : [[[], container]]
end

Class Method Details

.dotted_to_container(path, value, result = nil) ⇒ Hash, Array

Insert extended value value into struct result at path

Parameters:

  • path (String)

    Dotted path in container

  • value (String)

    Last value to insert

  • result (NilClass, Hash, Array) (defaults to: nil)

    current value

Returns:



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/aspera/dot_container.rb', line 14

def dotted_to_container(path, value, result = nil)
  # Typed keys
  keys = path.split(OPTION_DOTTED_SEPARATOR).map{ |k| int_or_string(k)}
  # Create, or re-use first level container
  current = (result ||= new_hash_or_array_from_key(keys.first))
  # walk the path, and create sub-containers if necessary
  keys.each_cons(2) do |k, next_k|
    array_requires_integer_index!(current, k)
    current = (current[k] ||= new_hash_or_array_from_key(next_k))
  end
  # Assign value at last index
  array_requires_integer_index!(current, keys.last)
  current[keys.last] = value
  result
end

Instance Method Details

#to_dottedHash

Convert nested Hash/Array container to dotted-path Hash

Returns:

  • (Hash)

    Dotted-path Hash



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/aspera/dot_container.rb', line 60

def to_dotted
  result = {}
  until @stack.empty?
    path, current = @stack.pop
    to_insert = nil
    # empty things are left intact
    if current.respond_to?(:empty?) && current.empty?
      to_insert = current
    else
      case current
      when Hash
        add_elements(path, current)
      when Array
        # Array has no nested structures -> list of Strings
        if current.none?{ |i| i.is_a?(Array) || i.is_a?(Hash)}
          to_insert = current.map(&:to_s)
        # Array of Hashes with only 'name' keys -> list of Strings
        elsif current.all?{ |i| i.is_a?(Hash) && i.keys == ['name']}
          to_insert = current.map{ |i| i['name']}
        # Array of Hashes with only 'name' and 'value' keys -> Hash of key/values
        elsif current.all?{ |i| i.is_a?(Hash) && i.keys.sort == %w[name value]}
          add_elements(path, current.each_with_object({}){ |i, h| h[i['name']] = i['value']})
        else
          add_elements(path, current.each_with_index.map{ |v, i| [i, v]})
        end
      else
        to_insert = current
      end
    end
    result[path.map(&:to_s).join(OPTION_DOTTED_SEPARATOR)] = to_insert unless to_insert.nil?
  end
  result
end