Class: ComputedModel::DepGraph Private

Inherits:
Object
  • Object
show all
Defined in:
lib/computed_model/dep_graph.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

A dependency graph representation used within ComputedModel::Model. Usually you don't need to use this class directly.

Examples:

graph = ComputedModel::DepGraph.new
graph << ComputedModel::DepGraph::Node.new(:computed, :foo, { bar: [] })
graph << ComputedModel::DepGraph::Node.new(:loaded, :bar, {})
plan = graph.tsort.plan([:foo])

Defined Under Namespace

Classes: Edge, Node, Sorted

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDepGraph

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of DepGraph.



17
18
19
# File 'lib/computed_model/dep_graph.rb', line 17

def initialize
  @nodes = {}
end

Class Method Details

.merge(graphs) ⇒ ComputedModel::DepGraph

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

Returns:



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/computed_model/dep_graph.rb', line 104

def self.merge(graphs)
  new_graph = ComputedModel::DepGraph.new
  nodes_by_name = graphs.flat_map(&:nodes).group_by(&:name)
  nodes_by_name.each do |name, nodes|
    type = nodes.first.type
    raise ArgumentError, "Field #{name} has multiple different types" unless nodes.all? { |node| node.type == type }

    new_graph << ComputedModel::DepGraph::Node.new(type, name, nodes.map { |n| n.edges.transform_values { |e| e.spec } })
  end
  new_graph
end

Instance Method Details

#<<(node) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Adds the new node.

Examples:

graph = ComputedModel::DepGraph.new
graph << ComputedModel::DepGraph::Node.new(:computed, :foo, {})

Parameters:

Raises:

  • (ArgumentError)

    when the node already exists



42
43
44
45
46
# File 'lib/computed_model/dep_graph.rb', line 42

def <<(node)
  raise ArgumentError, "Field already declared: #{node.name}" if @nodes.key?(node.name)

  @nodes[node.name] = node
end

#[](name) ⇒ Node?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the node with the specified name.

Examples:

graph = ComputedModel::DepGraph.new
graph[:foo]

Parameters:

  • name (Symbol)

    the name of the node

Returns:



29
30
31
# File 'lib/computed_model/dep_graph.rb', line 29

def [](name)
  @nodes[name]
end

#nodesArray<ComputedModel::DepGraph::Node>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:



49
50
51
# File 'lib/computed_model/dep_graph.rb', line 49

def nodes
  @nodes.values
end

#tsortComputedModel::DepGraph::Sorted

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Preprocess the graph by topological sorting. This is a necessary step for loader planning.

Examples:

graph = ComputedModel::DepGraph.new
graph << ComputedModel::DepGraph::Node.new(:computed, :foo, { bar: [] })
graph << ComputedModel::DepGraph::Node.new(:loaded, :bar, {})
sorted = graph.tsort

Returns:

Raises:

  • (ArgumentError)


62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/computed_model/dep_graph.rb', line 62

def tsort
  load_order = []
  visiting = Set[]
  visited = Set[]

  @nodes.each_value do |node|
    next unless node.type == :primary

    load_order << node.name
    visiting.add node.name
    visited.add node.name
  end

  raise ArgumentError, 'No primary loader defined' if load_order.empty?
  raise "Multiple primary fields: #{load_order.inspect}" if load_order.size > 1

  @nodes.each_value do |node|
    tsort_dfs(node.name, load_order, visiting, visited)
  end

  nodes_in_order = load_order.reverse.map { |name| @nodes[name] }
  ComputedModel::DepGraph::Sorted.new(self, nodes_in_order)
end