require 'tempfile' module UniverseCompiler module Utils module Graphviz 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 end end end