module UniverseCompiler::Utils::Graphviz

Public Instance Methods

graph_entities_to_file(entities, options = {}) { |g| ... } click to toggle source
# 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