File: deep_fetch.rb

package info (click to toggle)
ruby-hashie 5.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 856 kB
  • sloc: ruby: 7,042; sh: 8; makefile: 6
file content (31 lines) | stat: -rw-r--r-- 1,088 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
module Hashie
  module Extensions
    # Searches a deeply nested datastructure for a key path, and returns the associated value.
    #
    #  options = { user: { location: { address: '123 Street' } } }
    #  options.deep_fetch :user, :location, :address #=> '123 Street'
    #
    # If a block is provided its value will be returned if the key does not exist.
    #
    #  options.deep_fetch(:user, :non_existent_key) { 'a value' } #=> 'a value'
    #
    # This is particularly useful for fetching values from deeply nested api responses
    #   or params hashes.
    module DeepFetch
      class UndefinedPathError < StandardError; end

      def deep_fetch(*args, &block)
        args.reduce(self) do |obj, arg|
          begin
            arg = Integer(arg) if obj.is_a? Array
            obj.fetch(arg)
          rescue ArgumentError, IndexError, NoMethodError => e
            break yield(arg) if block
            raise UndefinedPathError,
                  "Could not fetch path (#{args.join(' > ')}) at #{arg}", e.backtrace
          end
        end
      end
    end
  end
end