Module: TrickBag::CollectionAccess

Defined in:
lib/trick_bag/collections/collection_access.rb

Defined Under Namespace

Classes: Error

Class Method Summary collapse

Class Method Details

.access(collection, key_string_or_array, separator = '.') ⇒ Object

Accesses a collection with a single string that represents n levels of depth. See the spec file for examples, but here’s one:

h = { ‘h’ => [‘a’, ‘b’] } CollectionAccess.access(h, ‘h.1’) => ‘b’

If an error is raised while trying to access the value with a given key, an error will be raised showing that error plus the context of which key failed, as in:

Error occurred processing key [x.1] in [x.1.2]: undefined method ‘[]’ for nil:NilClass

Parameters:

  • collection

    the collection to access

  • key_string_or_array

    the string or array representing the keys to use

  • separator (defaults to: '.')

    the string to use to separate the keys, defaults to ‘.’



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/trick_bag/collections/collection_access.rb', line 44

def access(collection, key_string_or_array, separator = '.')

  to_integer = ->(object) do
    begin
      Integer(object)
    rescue
      raise Error.new("Key cannot be converted to an Integer: #{object}")
    end
  end

  get_key_array = -> do
    case key_string_or_array
      when Array
        key_string_or_array
      when String
        key_string_or_array.split(separator)
      else
        raise Error.new("Invalid data type: #{key_string_or_array.class}")
    end
  end

  keys = get_key_array.()
  return_object = collection

  keys.each_with_index do |key, index|
    key = to_integer.(key) if return_object.kind_of?(Array)

    begin
      return_object = return_object[key]
    rescue => e
      this_key = keys[0..index].join(separator)
      raise Error.new("Error occurred processing key [#{this_key}] in [#{key_string_or_array}]: #{e}")
    end
  end
  return_object
end

.accessor(collection, separator = '.') ⇒ Object

Like access, but returns a lambda that can be used to access a given collection. Since lambdas can be called with the subscript operator, using it can resemble regular hash or array access. If you don’t like this you can use ‘.call’ or ‘.()’ instead.

An example:

h = { ‘h’ => [‘a’, ‘b’] } accessor = CollectionAccess.accessor(h) accessor # => ‘b’ or accessor.(‘h.1’) # => ‘b’



94
95
96
97
98
99
# File 'lib/trick_bag/collections/collection_access.rb', line 94

def accessor(collection, separator = '.')
  ->(*args) do
    key_string = (args.size == 1) ? args.first : args.map(&:to_s).join(separator)
    access(collection, key_string, separator)
  end
end