require 'tempfile' module UniverseCompiler module Utils module Graphviz def graph_entities_to_file(entities, output_file_name: nil, file_type: :svg, generate_file: true, &block) g = GraphViz.new( :G, :type => :digraph ) 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] unless target.nil? when :has_many entity[field_name].each do |target| g.add_edges cache[:by_entity][entity], cache[:by_entity][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