# frozen_string_literal: true
load 'rails_erd/tasks.rake' require 'rails_erd/diagram' require 'csv'
class TableSchema
def initialize(table_name) if table_name.split('.').size > 1 @schema, @name = table_name.split('.') else @schema = 'public' @name = table_name end end attr_reader :name attr_reader :schema
end
class DrawerdDiagram < RailsERD::Diagram
setup do @table_csv = CSV.open(Rails.root.join('tables.csv'), 'wb') @relation_csv = CSV.open(Rails.root.join('relations.csv'), 'wb') @table_csv << %w[table_schema table_name column_name column_type ordinal_position is_nullable primary_key column_comment table_comment] @relation_csv << %w[schema table column no relation_table_schema relation_table relation_column constraint_name relation_type] end each_entity do |entity| model = entity.model table_name = model.table_name table_comment = ActiveRecord::Base.connection.table_comment(table_name) table_name = TableSchema.new(table_name).name table_schema = TableSchema.new(table_name).schema entity.attributes.each_with_index do |attribute, ordinal_position| column = attribute.column column_name = column.name column_type = column.type is_nullable = column.null ? 't' : 'f' primary_key = model.primary_key == column.name ? 't' : 'f' column_comment = column.comment @table_csv << [table_schema, table_name, column_name, column_type, ordinal_position, is_nullable, primary_key, column_comment, table_comment] end end # Invoked once for each relationship each_relationship do |relationship| source = relationship.source des = relationship.destination source_model = source.model des_model = des.model next if source_model.nil? || des_model.nil? source_table_name = source_model.table_name des_table_name = des_model.table_name schema = TableSchema.new(source_table_name).schema table = TableSchema.new(source_table_name).name relation_table_schema = TableSchema.new(des_table_name).schema relation_table = TableSchema.new(des_table_name).name # TODO: fix mutual association unless relationship.indirect? if ass = relationship.associations.find { |x| x.macro == :has_many || x.macro == :has_one } column = ass.association_primary_key relation_column = ass.foreign_key end if relationship.many_to? && !relationship.many_to_many? if ass = relationship.associations.find { |x| x.macro == :belongs_to } column = ass.association_primary_key relation_column = ass.foreign_key end schema, table, column, relation_table_schema, relation_table, relation_colunm = relation_table_schema, relation_table, relation_colunm, schema, table, column end end relation_type = if relationship.one_to_one? then 'one' elsif relationship.indirect? && relationship.one_to_many? then 'm2m' elsif relationship.one_to_many? then 'many' elsif relationship.many_to_many? then 'm2m' end @relation_csv << [schema, table, column, 1, relation_table_schema, relation_table, relation_column, nil, relation_type] end # Should save or return the generated diagram save do @table_csv.close @relation_csv.close end
end
namespace :drawerd do
desc "generate CSV file for drawerd services" task generate: ['erd:check_dependencies', 'erd:options', 'erd:load_models'] do say "Generating CSV for #{ActiveRecord::Base.descendants.length} models..." DrawerdDiagram.create say "Done! Saved tables.csv to #{Rails.root.join('tables.csv')}." say "Done! Saved relations.csv to #{Rails.root.join('relations.csv')}." end
end