app/controllers/erd/erd_controller.rb in erd-0.6.4 vs app/controllers/erd/erd_controller.rb in erd-0.7.0

- old
+ new

@@ -4,66 +4,68 @@ require 'ruby-graphviz' require 'erd/application_controller' module Erd class ErdController < ::Erd::ApplicationController + POSITIONS_JSON_FILE = Rails.root.join('tmp/erd_positions.json').freeze + def index - plain = generate_plain - positions = if (json = Rails.root.join('tmp/erd_positions.json')).exist? - ActiveSupport::JSON.decode json.read - else - {} - end - @erd = render_plain plain, positions + @erd = render_plain generate_plain, saved_positions + end + def edit + @erd = render_plain generate_plain, saved_positions, true @migrations = Erd::Migrator.status end def update + if params[:position_changes].present? + position_changes = ActiveSupport::JSON.decode(params[:position_changes]) + positions = saved_positions + positions.merge! position_changes.transform_keys(&:tableize) + POSITIONS_JSON_FILE.open('w') {|f| f.write positions.to_json } + end + changes = params[:changes].present? ? ActiveSupport::JSON.decode(params[:changes]) : [] executed_migrations, failed_migrations = [], [] changes.each do |row| begin action, model, column, from, to = row['action'], row['model'], row['column'], row['from'], row['to'] - if action == 'move' + + case action + when 'create_model' + columns = column.split(' ').compact + generated_migration_file = Erd::GenaratorRunner.execute_generate_model model, columns + when 'remove_model' model = model.tableize - json_file = Rails.root.join('tmp', 'erd_positions.json') - positions = json_file.exist? ? ActiveSupport::JSON.decode(json_file.read) : {} - positions[model] = to - json_file.open('w') {|f| f.write positions.to_json} + generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "drop_#{model}" + gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n drop_table :#{model}\n end" + when 'rename_model' + _model, from, to = from.tableize, to.tableize, model.tableize + generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{from}_to_#{to}" + gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_table :#{from}, :#{to}\n end" + when 'add_column' + model = model.tableize + name_and_type = column.scan(/(.*)\((.*?)\)/).first + name, type = name_and_type[0], name_and_type[1] + generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"] + when 'rename_column' + model = model.tableize + generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{model}_#{from}_to_#{to}" + gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end" + when 'alter_column' + model = model.tableize + generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}" + gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end" + when 'move' + # do nothing else - case action - when 'create_model' - columns = column.split(' ').compact - generated_migration_file = Erd::GenaratorRunner.execute_generate_model model, columns - when 'remove_model' - model = model.tableize - generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "drop_#{model}" - gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n drop_table :#{model}\n end" - when 'rename_model' - _model, from, to = from.tableize, to.tableize, model.tableize - generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{from}_to_#{to}" - gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_table :#{from}, :#{to}\n end" - when 'add_column' - model = model.tableize - name_and_type = column.scan(/(.*)\((.*?)\)/).first - name, type = name_and_type[0], name_and_type[1] - generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"] - when 'rename_column' - model = model.tableize - generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{model}_#{from}_to_#{to}" - gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end" - when 'alter_column' - model = model.tableize - generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}" - gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end" - else - raise "unexpected action: #{action}" - end - Erd::Migrator.run_migrations :up => generated_migration_file - executed_migrations << generated_migration_file + raise "unexpected action: #{action}" end + + Erd::Migrator.run_migrations :up => generated_migration_file + executed_migrations << generated_migration_file rescue ::Erd::MigrationError => e failed_migrations << e.message end end @@ -75,10 +77,14 @@ redirect_to erd.root_path, :flash => {:executed_migrations => params.slice(:up, :down)} end private + def saved_positions + POSITIONS_JSON_FILE.exist? ? ActiveSupport::JSON.decode(POSITIONS_JSON_FILE.read) : {} + end + def generate_plain if Rails.respond_to?(:autoloaders) && Rails.autoloaders.try(:zeitwerk_enabled?) Zeitwerk::Loader.eager_load_all else Rails.application.eager_load! @@ -113,23 +119,24 @@ end } g.output('plain' => String) end - def render_plain(plain, positions) + def render_plain(plain, positions, edit_mode = false) _scale, svg_width, svg_height = plain.scan(/\Agraph ([\d\.]+) ([\d\.]+) ([\d\.]+)$/).first # node name x y width height label style shape color fillcolor - max_model_x, max_model_y = 0, 0 models = plain.scan(/^node ([^ ]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([^ ]+) [^ ]+ [^ ]+ [^ ]+ [^ ]+\n/m).map {|model_name, x, y, width, height, label| columns = label.gsub("\\\n", '').split('|')[1].split('\l').map {|name_and_type| name_and_type.scan(/(.*?)\((.*?)\)/).first }.map {|n, t| {:name => n, :type => t} } custom_x, custom_y = positions[model_name.tableize].try(:split, ',') - h = {:model => model_name, :x => (custom_x || (BigDecimal(x) * 72).round), :y => (custom_y || (BigDecimal(y) * 72).round), :width => (BigDecimal(width) * 72).round, :height => height, :columns => columns} - max_model_x, max_model_y = [h[:x].to_i + h[:width].to_i, max_model_x, 1024].max, [h[:y].to_i + h[:height].to_i, max_model_y, 768].max - h + {:model => model_name, :x => (custom_x || (BigDecimal(x) * 72).round), :y => (custom_y || (BigDecimal(y) * 72).round), :width => (BigDecimal(width) * 72).round, :height => (BigDecimal(height) * 72).round, :columns => columns} }.compact + max_model_x = models.map {|m| m[:x].to_f + m[:width].to_f }.max + erd_width = [[(BigDecimal(svg_width) * 72).round, max_model_x].min + 150, 1024].max + max_model_y = models.map {|m| m[:y].to_f + m[:height].to_f }.max + erd_height = [[(BigDecimal(svg_height) * 72).round, max_model_y].min + 150, 768].max # edge tail head n x1 y1 .. xn yn [label xl yl] style color edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from, :to => to}} - render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => [(BigDecimal(svg_width) * 72).round, max_model_x].max, :height => [(BigDecimal(svg_height) * 72).round, max_model_y].max, :models => models, :edges => edges} + render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => erd_width, :height => erd_height, :models => models, :edges => edges, :edit_mode => edit_mode} end def gsub_file(path, flag, *args, &block) path = File.expand_path path, Rails.root