Module: Igniter::Contracts::Assembly::PathAccess

Defined in:
lib/igniter/contracts/assembly/path_access.rb

Constant Summary collapse

NO_DEFAULT =
Object.new.freeze

Class Method Summary collapse

Class Method Details

.fetch_path(source, path, source_name:, keyword_name:, default: NO_DEFAULT) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/igniter/contracts/assembly/path_access.rb', line 28

def fetch_path(source, path, source_name:, keyword_name:, default: NO_DEFAULT)
  current = source

  path.each do |segment|
    if segment_present?(current, segment)
      current = fetch_segment(current, segment)
    else
      return default unless default.equal?(NO_DEFAULT)

      raise KeyError, "#{keyword_name} path #{format_path(path)} not present in #{source_name}"
    end
  end

  current
end

.fetch_segment(value, segment) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/igniter/contracts/assembly/path_access.rb', line 62

def fetch_segment(value, segment)
  return value.fetch(segment) if value.respond_to?(:key?) && value.key?(segment)
  return value.fetch(segment.to_s) if value.respond_to?(:key?) && segment.is_a?(Symbol) && value.key?(segment.to_s)
  return value.fetch(segment.to_sym) if value.respond_to?(:key?) && segment.is_a?(String) && value.key?(segment.to_sym)

  value.fetch(segment)
end

.format_path(path) ⇒ Object



70
71
72
# File 'lib/igniter/contracts/assembly/path_access.rb', line 70

def format_path(path)
  path.map(&:inspect).join(" -> ")
end

.normalize_path(keyword_name:, key: nil, dig: nil) ⇒ Object

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/igniter/contracts/assembly/path_access.rb', line 11

def normalize_path(keyword_name:, key: nil, dig: nil)
  raise ArgumentError, "#{keyword_name} accepts either key: or dig:, not both" if !key.nil? && !dig.nil?

  raw_path =
    if !key.nil?
      [key]
    elsif !dig.nil?
      Array(dig)
    else
      raise ArgumentError, "#{keyword_name} requires key: or dig:"
    end

  raise ArgumentError, "#{keyword_name} dig: path cannot be empty" if raw_path.empty?

  raw_path.map { |segment| normalize_segment(segment) }
end

.normalize_segment(segment) ⇒ Object



44
45
46
47
48
# File 'lib/igniter/contracts/assembly/path_access.rb', line 44

def normalize_segment(segment)
  return segment if segment.is_a?(Integer)

  segment.to_sym
end

.segment_present?(value, segment) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
53
54
55
56
57
58
59
60
# File 'lib/igniter/contracts/assembly/path_access.rb', line 50

def segment_present?(value, segment)
  if value.respond_to?(:key?)
    value.key?(segment) ||
      (segment.is_a?(Symbol) && value.key?(segment.to_s)) ||
      (segment.is_a?(String) && value.key?(segment.to_sym))
  elsif value.is_a?(Array) && segment.is_a?(Integer)
    segment >= 0 && segment < value.length
  else
    false
  end
end