app/controllers/erd/erd_controller.rb in erd-0.1.2 vs app/controllers/erd/erd_controller.rb in erd-0.1.3

- old
+ new

@@ -1,13 +1,10 @@ -require 'rails/generators' require 'nokogiri' require 'rails_erd/diagram/graphviz' require 'erd/application_controller' module Erd - class MigrationError < StandardError; end - class ErdController < ::Erd::ApplicationController def index Rails.application.eager_load! RailsERD.options[:filename], RailsERD.options[:filetype] = Rails.root.join('tmp/erd'), 'plain' RailsERD::Diagram::Graphviz.create @@ -17,53 +14,36 @@ else {} end @erd = render_plain plain, positions - migrated_versions = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}").map {|v| '%.3d' % v} - @migrations = [] - ActiveRecord::Migrator.migrations_paths.each do |path| - Dir.foreach(Rails.root.join(path)) do |file| - if (version_and_name = /^(\d{3,})_(.+)\.rb$/.match(file)) - status = migrated_versions.delete(version_and_name[1]) ? 'up' : 'down' - @migrations << {status: status, version: version_and_name[1], name: version_and_name[2]} - end - end - end - @migrations += migrated_versions.map {|v| {status: 'up', version: v, name: '*** NO FILE ***'}} - @migrations.sort_by! {|m| m[:version]} + @migrations = Erd::Migrator.status end def update changes = ActiveSupport::JSON.decode(params[:changes]) failed_migrations = [] changes.each do |row| begin action, model, column, from, to = row['action'], row['model'].tableize, row['column'], row['from'], row['to'] - before_migration_files = Dir.glob Rails.root.join('db', 'migrate', '*.rb') case action when 'remove_model' - execute_generate_migration "drop_#{model}" - generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first + generated_migration_file = Erd::Migrator.execute_generate_migration "drop_#{model}" gsub_file generated_migration_file, /def up.* end/m, "def change\n drop_table :#{model}\n end" when 'rename_model' from, to = from.tableize, to.tableize - execute_generate_migration "rename_#{from}_to_#{to}" - generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first + generated_migration_file = Erd::Migrator.execute_generate_migration "rename_#{from}_to_#{to}" gsub_file generated_migration_file, /def up.* end/m, "def change\n rename_table :#{from}, :#{to}\n end" when 'add_column' name_and_type = column.scan(/(.*)\((.*?)\)/).first name, type = name_and_type[0], name_and_type[1] - execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"] - generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first + Erd::Migrator.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"] when 'rename_column' - execute_generate_migration "rename_#{model}_#{from}_to_#{to}" - generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first + generated_migration_file = Erd::Migrator.execute_generate_migration "rename_#{model}_#{from}_to_#{to}" gsub_file generated_migration_file, /def up.* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end" when 'alter_column' - execute_generate_migration "change_#{model}_#{column}_type_to_#{to}" - generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first + generated_migration_file = Erd::Migrator.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}" gsub_file generated_migration_file, /def up.* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end" when 'move' json_file = Rails.root.join('tmp', 'erd_positions.json') positions = json_file.exist? ? ActiveSupport::JSON.decode(json_file.read) : {} positions[model] = to @@ -78,63 +58,32 @@ redirect_to erd.root_path, :flash => {:failed_migrations => failed_migrations} end def migrate - run_migrations :up => params[:up], :down => params[:down] + Erd::Migrator.run_migrations :up => params[:up], :down => params[:down] redirect_to erd.root_path end private def render_plain(plain, positions) _scale, svg_width, svg_height = plain.scan(/\Agraph ([0-9\.]+) ([0-9\.]+) ([0-9\.]+)$/).first ratio = [BigDecimal('4800') / BigDecimal(svg_width), BigDecimal('3200') / BigDecimal(svg_height), 180].min # node name x y width height label style shape color fillcolor models = plain.scan(/^node ([^ ]+) ([0-9\.]+) ([0-9\.]+) ([0-9\.]+) ([0-9\.]+) <\{?(<((?!^\}?>).)*)^\}?> [^ ]+ [^ ]+ [^ ]+ [^ ]+\n/m).map {|node_name, x, y, width, height, label| label_doc = Nokogiri::HTML::DocumentFragment.parse(label) - model_name = label_doc.search('table')[0].search('tr > td').first.text + model_name = node_name.sub(/^m_/, '') next if model_name == 'ActiveRecord::SchemaMigration' columns = [] if (cols_table = label_doc.search('table')[1]) columns = cols_table.search('tr > td').map {|col| col_name, col_type = col.text.split(' '); {:name => col_name, :type => col_type}} end custom_x, custom_y = positions[model_name.tableize].try(:split, ',') - {:model => model_name, :name => node_name, :x => (custom_x || BigDecimal(x) * ratio), :y => (custom_y || BigDecimal(y) * ratio), :width => BigDecimal(width) * ratio, :height => height, :columns => columns} + {:model => model_name, :x => (custom_x || BigDecimal(x) * ratio), :y => (custom_y || BigDecimal(y) * ratio), :width => BigDecimal(width) * ratio, :height => height, :columns => columns} }.compact # edge tail head n x1 y1 .. xn yn [label xl yl] style color - edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from, :to => to}} + edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from.sub(/^m_/, ''), :to => to.sub(/^m_/, '')}} render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => BigDecimal(svg_width) * ratio, :height => BigDecimal(svg_height) * ratio, :models => models, :edges => edges} - end - - def execute_generate_migration(name, options = nil) - overwriting_argv([name, options]) do - Rails::Generators.configure! Rails.application.config.generators - result = Rails::Generators.invoke 'migration', [name, options], :behavior => :invoke, :destination_root => Rails.root - raise ::Erd::MigrationError, "#{name}#{"(#{options})" if options}" unless result - end - end - - # `rake db:migrate` - def run_migrations(migrations) - migrations.each do |direction, versions| - versions.each do |version| - ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_path, version.to_i) - end if versions - end - if ActiveRecord::Base.schema_format == :ruby - File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", 'w') do |file| - ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) - end - end - end - - # a dirty workaround to make rspec-rails run - def overwriting_argv(value, &block) - original_argv = ARGV - Object.const_set :ARGV, value - block.call - ensure - Object.const_set :ARGV, original_argv end def gsub_file(path, flag, *args, &block) path = File.expand_path path, Rails.root