Created
August 23, 2019 16:49
-
-
Save wycleffsean/b7ac7ebfa2754c3e2760c6a57393e308 to your computer and use it in GitHub Desktop.
Generate Entity Relationship Model for ActiveRecord with GraphViz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace :graph do | |
desc 'build graph of AR models' | |
task models: :environment do | |
require 'graphviz' | |
Rails.application.eager_load! | |
g = GraphViz.new('Models', path: Rails.root.join('tmp').to_s) | |
nodes = ObjectSpace.each_object(Class) | |
.select { |c| c < ActiveRecord::Base } | |
.map { |c| GraphNode.new(g, c) } | |
nodes | |
.each { |m| m.nodes = nodes } | |
.each(&:call) | |
g.output(png: "models.png") | |
end | |
end | |
class GraphNode < Struct.new(:g, :model) | |
attr_accessor :nodes | |
attr_reader :node | |
def initialize(*args) | |
super | |
@node = g.add_nodes(model.name) | |
end | |
def call | |
add_parents | |
add_children | |
end | |
def add_parents | |
reflections(kind: :belongs_to).each do |parent| | |
g.add_edges(@node, parent.node, style: "solid" ) | |
end | |
end | |
def add_children | |
reflections(kind: :has_many).each do |child| | |
g.add_edges(@node, child.node, style: "dotted" ) | |
end | |
reflections(kind: :has_one).each do |child| | |
g.add_edges(@node, child.node, style: "dotted" ) | |
end | |
end | |
def reflections(kind:) | |
model.reflections | |
.select { |_, assoc| assoc.macro == kind } | |
.map { |label, assoc| | |
begin | |
nodes.find{|n| n.model == assoc.klass} | |
rescue NameError => e | |
puts '-'*80 | |
puts "for #{model.name}" | |
puts e | |
puts '-'*80 | |
nil | |
end | |
}.compact | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment