Module: UniverseCompiler::Utils::Graphviz

Defined in:
lib/universe_compiler/utils/graphviz.rb

Instance Method Summary collapse

Instance Method Details

#graph_entities_to_file(entities, options = {}, &block) ⇒ Object



8
9
10
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/universe_compiler/utils/graphviz.rb', line 8

def graph_entities_to_file(entities, options = {}, &block)

  graph_type = options.fetch :graph_type, :digraph
  output_file_name = options.fetch :output_file_name, nil
  file_type = options.fetch :file_type, :svg
  generate_file = options.fetch :generate_file, true
  error_level = options.fetch :error_level, 1
  parent_graph = options.fetch :parent_graph, nil
  program = options.fetch :program, :dot

  graph_options = { type: graph_type,
                    errors: error_level,
                    use: program,
                    parent: parent_graph
  }

  g = GraphViz.new :G, graph_options

  cache = {by_node: {}, by_entity: {}}
  # Building nodes 
  entities.each do |entity|
    node = g.add_node entity.as_path
    if entity.respond_to? :graphviz_label
      node[:label] = entity.graphviz_label
    end
    cache[:by_entity][entity] = node
    cache[:by_node][node] = entity
  end

  # Building relations
  entities.each do |entity|
    entity.class.fields_constraints.each do |field_name, field_constraints|
      field_constraints.each do |constraint_name, _|
        case constraint_name
        when :has_one
          target = entity[field_name]
          g.add_edges cache[:by_entity][entity], cache[:by_entity][target] if entities.include? target
        when :has_many
          entity[field_name].each do |target|
            g.add_edges cache[:by_entity][entity], cache[:by_entity][target] if entities.include? target
          end
        end
      end
    end
  end

  if block_given?
    case block.arity
    when 1
      yield g
    when 2
      yield g, cache
    else
      raise UniverseCompiler::Error, 'Wrong arity when calling UniverseCompiler::Utils::Graphviz#graph_entities_to_file'
    end
  end

  file_ext = file_type.to_s
  file_ext = (file_ext.start_with? '.') ? file_ext : ".#{file_ext}"

  output_file_name = case output_file_name
                     when NilClass
                       file = Tempfile.create ['entities_graph', file_ext]
                       file.close
                       file.path
                     when String
                       if output_file_name.end_with? file_ext
                         output_file_name
                       else
                         "#{output_file_name}#{file_ext}"
                       end
                     end

  if generate_file
    g.output( file_type => output_file_name )
    UniverseCompiler.logger.debug "Graph file: '#{output_file_name}'"
    output_file_name
  else
    g
  end
end