Module: RespondToDig

Defined in:
lib/respond_to_dig.rb,
lib/respond_to_dig/version.rb

Overview

Extracts the nested value specified by the sequence of index by calling dig at each step, returning nil if any intermediate step is nil.

Examples:

h = RespondToDig.invoke({ foo: {bar: {baz: 1 }}})
h.dig(:foo, :bar, :baz)           #=> 1
h.dig(:foo, :zot, :xyz)           #=> nil
h.dig(:foo, :bar, :baz, :xyz)     #=> TypeError

g = RespondToDig.invoke({ foo: [10, 11, 12] })
g.dig(:foo, 1)                    #=> 11

Constant Summary collapse

VERSION =
'1.2.0'.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.diggable?(target) ⇒ Bool

Note:

The reason why not purely duck typed by ‘[]` method is to avoid unexpected behavior, for example we won’t get ‘’o’‘ by `’foo’.dig(1)‘ by String#[].

Returns whether the ‘target` object is able to be invoked by `RespondToDig`

Parameters:

  • target (Object)

Returns:

  • (Bool)


29
30
31
32
33
# File 'lib/respond_to_dig.rb', line 29

def diggable?(target)
  target.is_a? Enumerable and
      target.respond_to? :[] and
      not target.respond_to? :dig
end

.respond_to_dig(receiver) ⇒ Object, RespondToDig Also known as: invoke_dig, invoke

Invokes ‘RespondToDig` module if the `receiver` object is digabble

Parameters:

  • receiver (Object)

Returns:

See Also:

  • #digabble


18
19
20
21
22
# File 'lib/respond_to_dig.rb', line 18

def respond_to_dig(receiver)
  receiver.tap do |r|
    r.singleton_class.send(:include, RespondToDig) if RespondToDig.diggable? r
  end
end

Instance Method Details

#dig(key, *rest) ⇒ Object, ...

Retrieves the value object corresponding to the each ‘key` objects recursively with nil-safe

Parameters:

  • key (Object, ...)

Returns:

Raises:

  • (TypeError)

    Throws if trying to access the value which doesn’t respond to ‘#dig` such as `String` object



44
45
46
47
48
49
50
51
52
53
# File 'lib/respond_to_dig.rb', line 44

def dig(key, *rest)
  value = RespondToDig.invoke(self[key])
  if value.nil? || rest.empty?
    value
  elsif value.respond_to?(:dig)
    value.dig(*rest)
  else
    fail TypeError, "#{value.class} does not have #dig method"
  end
end