Class: LazyGraph::ObjectNode

Inherits:
Node
  • Object
show all
Defined in:
lib/lazy_graph/node/object_node.rb,
lib/lazy_graph/node/symbol_hash.rb

Defined Under Namespace

Classes: SymbolHash

Constant Summary

Constants included from Node::DerivedRules

Node::DerivedRules::PLACEHOLDER_VAR_REGEX

Instance Attribute Summary collapse

Attributes inherited from Node

#children, #depth, #derived, #invisible, #is_object, #name, #namespace, #parent, #path, #root, #type

Instance Method Summary collapse

Methods inherited from Node

#absolute_path, #ancestors, #build_caster, #build_derived_inputs!, #clear_visits!, #copy_item!, #define_missing_value_proc!, #derive_item!, #fetch_and_resolve, #fetch_item, #initialize, #lazy_init_node!, #raise_presence_validation_error!, #resolve_relative_input, #simple?, #trace!

Methods included from Node::DerivedRules

#build_derived_inputs, #create_derived_input_context, #extract_derived_src, extract_expr_from_source_location, get_file_body, #interpret_derived_proc, #map_derived_inputs_to_paths, #parse_args_with_conditions, #parse_derived_inputs, #parse_rule_string, #resolver_for, #rule_definition_backtrace

Constructor Details

This class inherits a constructor from LazyGraph::Node

Instance Attribute Details

#propertiesObject (readonly)

Returns the value of attribute properties.


5
6
7
# File 'lib/lazy_graph/node/object_node.rb', line 5

def properties
  @properties
end

Instance Method Details

#children=(value) ⇒ Object


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/lazy_graph/node/object_node.rb', line 71

def children=(value)
  @children = value

  @properties = @children.fetch(:properties, {}).compare_by_identity
  @pattern_properties = @children.fetch(:pattern_properties, [])

  @complex_properties_a = @properties.to_a.reject { _2.simple? }
  @complex_pattern_properties_a = @pattern_properties.reject { _2.simple? }

  @has_properties = @properties.any? || @pattern_properties.any?

  return unless @has_properties

  if @pattern_properties.any?
    @property_class = SymbolHash
  else
    invisible = @properties.select { |_k, v| v.invisible }.map(&:first)
    @property_class = LazyGraph.fetch_property_class(
      path,
      { members: @properties.keys + (@debug && !parent ? [:DEBUG] : []),
        invisible: invisible },
      namespace: root.namespace
    )
  end
  define_singleton_method(:cast, lambda { |val|
    if val.is_a?(MissingValue)
      val
    else
      val.is_a?(@property_class) ? val : @property_class.new(val.to_h)
    end
  })
end

#find_resolver_for(segment) ⇒ Object


61
62
63
64
65
66
67
68
69
# File 'lib/lazy_graph/node/object_node.rb', line 61

def find_resolver_for(segment)
  if segment.equal?(:'$')
    root
  elsif @properties.key?(segment)
    @properties[segment]
  else
    @parent&.find_resolver_for(segment)
  end
end

#resolve(path, stack_memory, should_recycle = stack_memory, preserve_keys: false) ⇒ Object

An object supports the following types of path resolutions.

  1. Property name: obj.property => value

  2. Property name group: obj[property1, property2] => { property1: value1, property2: value2 }

  3. All [*]


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/lazy_graph/node/object_node.rb', line 11

def resolve(
  path,
  stack_memory,
  should_recycle = stack_memory,
  preserve_keys: false
)
  input = stack_memory.frame

  @visited[(input.object_id >> 2 ^ path.shifted_id) + preserve_keys.object_id] ||= begin
    return input if input.is_a?(MissingValue)

    path_next = path.next

    if (path_segment = path.segment).is_a?(PathParser::PathGroup)
      return path_segment.options.each_with_object(SymbolHash.new) do |part, object|
        resolve(part.merge(path_next), stack_memory, nil, preserve_keys: object)
      end
    end
    if !segment = path_segment&.part
      @complex_properties_a.each do |key, node|
        node.fetch_and_resolve(path_next, input, key, stack_memory)
      end
      if @complex_pattern_properties_a.any?
        input.keys.each do |key|
          node = !@properties[key] && @complex_pattern_properties_a.find do |(pattern, _value)|
            pattern.match?(key)
          end&.last
          next unless node

          node.fetch_and_resolve(path_next, input, key, stack_memory)
        end
      end
      cast(input)
    elsif (prop = @properties[segment])
      prop.fetch_and_resolve(path_next, input, segment, stack_memory, preserve_keys)
    elsif (_, prop = @pattern_properties.find { |(key, _val)| key.match?(segment) })
      prop.fetch_and_resolve(path_next, input, segment, stack_memory, preserve_keys)
    elsif input&.key?(segment)
      prop = @properties[segment] = lazy_init_node!(input[segment], segment)
      @properties_a = @properties.to_a
      prop.fetch_and_resolve(path_next, input, segment, stack_memory, preserve_keys)
    else
      value = MissingValue()
      preserve_keys ? preserve_keys[segment] = value : value
    end
  end
ensure
  should_recycle&.recycle!
end