Class: ErdMap::Graph
- Inherits:
-
Object
- Object
- ErdMap::Graph
- Defined in:
- lib/erd_map/graph.rb
Constant Summary collapse
- CHUNK_SIZE =
3- MAX_COMMUNITY_SIZE =
20
Instance Method Summary collapse
- #association_columns ⇒ Object
-
#chunked_nodes ⇒ Object
[[nodeA, nodeB, nodeC], [nodeD, nodeE, nodeF, nodeG, …], …].
- #connections ⇒ Object
- #edges ⇒ Object
- #initial_layout ⇒ Object
- #initial_nodes ⇒ Object
- #layouts_by_chunk ⇒ Object
- #node_colors ⇒ Object
- #node_names ⇒ Object
- #node_radius ⇒ Object
- #node_with_community_index ⇒ Object
- #nodes_with_i18n_labels ⇒ Object
- #whole_layout ⇒ Object
Instance Method Details
#association_columns ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/erd_map/graph.rb', line 111 def association_columns return @association_columns if @association_columns @association_columns = Hash.new { |hash, key| hash[key] = [] } whole_models.each do |model| model.reflect_on_all_associations(:belongs_to).select { |mod| !mod.[:polymorphic] }.map do |target| if target.try(:foreign_key) && model.column_names.include?(target.foreign_key) @association_columns[model.name] << target.foreign_key end end end @association_columns end |
#chunked_nodes ⇒ Object
- [nodeA, nodeB, nodeC], [nodeD, nodeE, nodeF, nodeG, …], …
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/erd_map/graph.rb', line 34 def chunked_nodes return @chunked_nodes if @chunked_nodes centralities = networkx.eigenvector_centrality(whole_graph) # { node_name => centrality } sorted_nodes = centralities.sort_by { |_node, centrality| centrality }.reverse.map(&:first) chunk_sizes = [] total_nodes = sorted_nodes.size while chunk_sizes.sum < total_nodes chunk_sizes << (CHUNK_SIZE ** (chunk_sizes.size + 1)) end offset = 0 @chunked_nodes = chunk_sizes.each_with_object([]) do |size, nodes| slice = sorted_nodes[offset, size] break nodes if slice.nil? || slice.empty? offset += size nodes << slice end end |
#connections ⇒ Object
95 96 97 98 99 100 |
# File 'lib/erd_map/graph.rb', line 95 def connections @connections ||= edges.each_with_object(Hash.new { |hash, key| hash[key] = [] }) do |(a, b), hash| hash[a] << b hash[b] << a end end |
#edges ⇒ Object
87 88 89 |
# File 'lib/erd_map/graph.rb', line 87 def edges @edges ||= PyCall::List.new(whole_graph.edges) end |
#initial_layout ⇒ Object
75 76 77 |
# File 'lib/erd_map/graph.rb', line 75 def initial_layout layouts_by_chunk.first end |
#initial_nodes ⇒ Object
71 72 73 |
# File 'lib/erd_map/graph.rb', line 71 def initial_nodes chunked_nodes.first end |
#layouts_by_chunk ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/erd_map/graph.rb', line 9 def layouts_by_chunk return @layouts_by_chunk if @layouts_by_chunk @layouts_by_chunk = [] chunked_nodes.each_with_index do |_, i| display_nodes = chunked_nodes[0..i].flatten nodes_size = display_nodes.size k = 1.0 / Math.sqrt(nodes_size) * 3.0 subgraph = whole_graph.subgraph(display_nodes) layout = networkx.spring_layout(subgraph, seed: 1, k: k) layout_hash = {} layout.each do |node, xy| layout_hash[node] = [xy[0].to_f, xy[1].to_f] end @layouts_by_chunk << layout_hash end @layouts_by_chunk end |
#node_colors ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/erd_map/graph.rb', line 125 def node_colors return @node_colors if @node_colors palette = [ "#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e74446", "#fdbf6f", "#ff7f00", "#cab2d6", "#7850a4", "#ffff99", "#b8693d", "#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f", "#1b9e77", "#d95f02", "#7570b3", "#ef73b2", "#66a61e", "#e6ab02" ] community_map = node_with_community_index @node_colors = node_names.map do |node_name| community_index = community_map[node_name] palette[community_index % palette.size] end end |
#node_names ⇒ Object
83 84 85 |
# File 'lib/erd_map/graph.rb', line 83 def node_names @node_names ||= PyCall::List.new(whole_graph.nodes) end |
#node_radius ⇒ Object
91 92 93 |
# File 'lib/erd_map/graph.rb', line 91 def node_radius @node_radius ||= node_names.map { |node_name| nodes_with_radius_according_to_chunk_index[node_name] } end |
#node_with_community_index ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/erd_map/graph.rb', line 56 def node_with_community_index return @node_with_community_index if @node_with_community_index whole_communities = networkx_community.louvain_communities(whole_graph).map { |communities| PyCall::List.new(communities).to_a } communities = split_communities(whole_graph, whole_communities) @node_with_community_index = {} communities.each_with_index do |community, i| community.each do |node_name| @node_with_community_index[node_name] = i end end @node_with_community_index end |
#nodes_with_i18n_labels ⇒ Object
102 103 104 105 106 107 108 109 |
# File 'lib/erd_map/graph.rb', line 102 def nodes_with_i18n_labels return @nodes_with_i18n_labels if @nodes_with_i18n_labels @nodes_with_i18n_labels = {} whole_models.each do |model| @nodes_with_i18n_labels[model.name] = model.model_name.human(default: "") end @nodes_with_i18n_labels end |
#whole_layout ⇒ Object
79 80 81 |
# File 'lib/erd_map/graph.rb', line 79 def whole_layout layouts_by_chunk.last end |