erd 0.6.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +3 -4
- data/README.md +72 -0
- data/app/controllers/erd/erd_controller.rb +107 -65
- data/app/views/erd/erd/_column.html.erb +8 -4
- data/app/views/erd/erd/_model.html.erb +23 -17
- data/app/views/erd/erd/edit.html.erb +87 -0
- data/app/views/erd/erd/erd.html.erb +1 -1
- data/app/views/erd/erd/index.html.erb +12 -81
- data/app/views/layouts/erd/application.html.erb +3 -2
- data/config/routes.rb +1 -0
- data/erd.gemspec +1 -1
- data/gemfiles/rails_32.gemfile +1 -1
- data/gemfiles/rails_40.gemfile +1 -0
- data/gemfiles/rails_41.gemfile +1 -0
- data/gemfiles/rails_42.gemfile +1 -0
- data/gemfiles/rails_50.gemfile +1 -0
- data/gemfiles/rails_51.gemfile +1 -0
- data/gemfiles/rails_52.gemfile +1 -0
- data/gemfiles/rails_60.gemfile +9 -0
- data/gemfiles/rails_edge.gemfile +1 -0
- data/lib/erd.rb +7 -1
- data/lib/erd/engine.rb +12 -0
- data/lib/erd/migrator.rb +3 -1
- data/lib/erd/version.rb +1 -1
- data/{vendor/assets/images → public}/erd/angle-left.png +0 -0
- data/{vendor/assets/images → public}/erd/angle-right.png +0 -0
- data/{vendor/assets/images → public}/erd/animated-overlay.gif +0 -0
- data/{vendor/assets/images → public}/erd/background.png +0 -0
- data/{vendor/assets/images → public}/erd/cancel.png +0 -0
- data/{vendor/assets/images → public}/erd/close.png +0 -0
- data/public/erd/erd.css +598 -0
- data/{app/assets/javascripts/erd/erd.js.js → public/erd/erd.js} +13 -2
- data/{app → src}/assets/stylesheets/erd/erd.css.scss +1 -1
- data/test/test_helper.rb +2 -0
- metadata +21 -22
- data/README.rdoc +0 -66
- data/app/assets/javascripts/erd/application.js +0 -14
- data/app/assets/stylesheets/erd/application.css +0 -13
- data/lib/erd/railtie.rb +0 -21
- data/vendor/assets/javascripts/raphael-min.js +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23d4342f2a320f75b2e90d11bf2474d5f1878632369e6c5a9e3608f3c9ac9aee
|
4
|
+
data.tar.gz: d7b53a5993a0b95508e44be666ec68f620563e4a9ee7bfb7ef708f09beb0ffda
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37a889901a16afac747792e929a71a8831ff55b0119cdb5cf96911fb19447a493a717021c7a65c1e7d3274809af67dd64c6a0184f79aebfa09716198186d38f8
|
7
|
+
data.tar.gz: c87a23f1c22cbff2363b8f54d993be86669330854fd80bd9570df87b3f144434c9ad55aacceacdf08f95b0fe60ff0cf67d4a145ee1918c22c1cba2b7b8b31b15
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -14,7 +14,6 @@ cache:
|
|
14
14
|
|
15
15
|
before_install:
|
16
16
|
- sudo apt install -y chromium-chromedriver
|
17
|
-
- sudo ln -s /usr/lib/chromium-browser/chromedriver /usr/bin/
|
18
17
|
- gem i bundler -v '<2'
|
19
18
|
|
20
19
|
rvm:
|
@@ -22,6 +21,7 @@ rvm:
|
|
22
21
|
- 2.0.0
|
23
22
|
|
24
23
|
gemfile:
|
24
|
+
- gemfiles/rails_60.gemfile
|
25
25
|
- gemfiles/rails_52.gemfile
|
26
26
|
- gemfiles/rails_51.gemfile
|
27
27
|
- gemfiles/rails_50.gemfile
|
@@ -32,6 +32,8 @@ gemfile:
|
|
32
32
|
|
33
33
|
matrix:
|
34
34
|
exclude:
|
35
|
+
- rvm: 2.0.0
|
36
|
+
gemfile: gemfiles/rails_60.gemfile
|
35
37
|
- rvm: 2.0.0
|
36
38
|
gemfile: gemfiles/rails_52.gemfile
|
37
39
|
- rvm: 2.0.0
|
@@ -46,6 +48,3 @@ matrix:
|
|
46
48
|
gemfile: gemfiles/rails_40.gemfile
|
47
49
|
- rvm: 2.6.0
|
48
50
|
gemfile: gemfiles/rails_32.gemfile
|
49
|
-
include:
|
50
|
-
- rvm: 1.8.7
|
51
|
-
gemfile: gemfiles/rails_32.gemfile
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Erd
|
2
|
+
|
3
|
+
A Rails engine for drawing your app's ER diagram and operating migrations
|
4
|
+
|
5
|
+
|
6
|
+
## Requirements
|
7
|
+
|
8
|
+
* Rails 5.2, 5.1, 5.0, 4.2, 4.1, 4.0, 3.2, or 3.1
|
9
|
+
|
10
|
+
* Graphviz
|
11
|
+
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Bundle 'erd' gem to your existing Rails app's Gemfile:
|
16
|
+
```ruby
|
17
|
+
gem 'erd', group: :development
|
18
|
+
|
19
|
+
```
|
20
|
+
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Browse at your http://localhost:3000/erd
|
25
|
+
|
26
|
+
|
27
|
+
## Features
|
28
|
+
|
29
|
+
### Show Mode
|
30
|
+
|
31
|
+
* Erd draws an ER diagram based on your app's database and models.
|
32
|
+
|
33
|
+
* You can drag and arrange the positions of each model.
|
34
|
+
|
35
|
+
* Then you can save the positions to a local file `db/erd_positions.json`, so you can share the diagram between the team members.
|
36
|
+
|
37
|
+
### Edit Mode
|
38
|
+
|
39
|
+
* You can operate DB schema manipulations such as `add column`, `rename column`, `alter column`, `create model (as well as table)`, and `drop table`.
|
40
|
+
|
41
|
+
* Then, Erd generates migration files on the server.
|
42
|
+
|
43
|
+
* And you can run each migration on your browser super quickly.
|
44
|
+
|
45
|
+
|
46
|
+
## TODO
|
47
|
+
|
48
|
+
* Fix buggy JS
|
49
|
+
|
50
|
+
* drop column (need to think of the UI)
|
51
|
+
|
52
|
+
* stop depending on Graphviz
|
53
|
+
|
54
|
+
* tests
|
55
|
+
|
56
|
+
* cleaner code (the code is horrible. Please don't read the code, though of course your patches welcome)
|
57
|
+
|
58
|
+
|
59
|
+
## Contributing to Erd
|
60
|
+
|
61
|
+
* Send me your pull requests!
|
62
|
+
|
63
|
+
|
64
|
+
## Team
|
65
|
+
|
66
|
+
* [Akira Matsuda][https://github.com/amatsuda]
|
67
|
+
* [Teppei Machida][http://github.com/machida] (design)
|
68
|
+
|
69
|
+
|
70
|
+
## Copyright
|
71
|
+
|
72
|
+
Copyright (c) 2012 Akira Matsuda. See MIT-LICENSE for further details.
|
@@ -1,70 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'nokogiri'
|
4
|
-
require '
|
4
|
+
require 'ruby-graphviz'
|
5
5
|
require 'erd/application_controller'
|
6
6
|
|
7
7
|
module Erd
|
8
8
|
class ErdController < ::Erd::ApplicationController
|
9
|
+
POSITIONS_JSON_FILE = Rails.root.join('db/erd_positions.json').freeze
|
10
|
+
OLD_POSITIONS_JSON_FILE = Rails.root.join('db/erd_positions.json').freeze # for compatibility
|
11
|
+
|
9
12
|
def index
|
10
|
-
|
11
|
-
|
12
|
-
RailsERD::Diagram::Graphviz.create
|
13
|
-
plain = Rails.root.join('tmp/erd.plain').read
|
14
|
-
positions = if (json = Rails.root.join('tmp/erd_positions.json')).exist?
|
15
|
-
ActiveSupport::JSON.decode json.read
|
16
|
-
else
|
17
|
-
{}
|
18
|
-
end
|
19
|
-
@erd = render_plain plain, positions
|
13
|
+
@erd = render_plain generate_plain, saved_positions
|
14
|
+
end
|
20
15
|
|
16
|
+
def edit
|
17
|
+
@erd = render_plain generate_plain, saved_positions, true
|
21
18
|
@migrations = Erd::Migrator.status
|
22
19
|
end
|
23
20
|
|
24
21
|
def update
|
25
|
-
|
22
|
+
if params[:position_changes].present?
|
23
|
+
position_changes = ActiveSupport::JSON.decode(params[:position_changes])
|
24
|
+
positions = saved_positions
|
25
|
+
positions.merge! position_changes.transform_keys(&:tableize)
|
26
|
+
POSITIONS_JSON_FILE.open('w') {|f| f.write positions.to_json }
|
27
|
+
end
|
28
|
+
|
29
|
+
changes = params[:changes].present? ? ActiveSupport::JSON.decode(params[:changes]) : []
|
26
30
|
executed_migrations, failed_migrations = [], []
|
27
31
|
changes.each do |row|
|
28
32
|
begin
|
29
33
|
action, model, column, from, to = row['action'], row['model'], row['column'], row['from'], row['to']
|
30
|
-
|
34
|
+
|
35
|
+
case action
|
36
|
+
when 'create_model'
|
37
|
+
columns = column.split(' ').compact
|
38
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_model model, columns
|
39
|
+
when 'remove_model'
|
31
40
|
model = model.tableize
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
41
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "drop_#{model}"
|
42
|
+
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n drop_table :#{model}\n end"
|
43
|
+
when 'rename_model'
|
44
|
+
_model, from, to = from.tableize, to.tableize, model.tableize
|
45
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{from}_to_#{to}"
|
46
|
+
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_table :#{from}, :#{to}\n end"
|
47
|
+
when 'add_column'
|
48
|
+
model = model.tableize
|
49
|
+
name_and_type = column.scan(/(.*)\((.*?)\)/).first
|
50
|
+
name, type = name_and_type[0], name_and_type[1]
|
51
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"]
|
52
|
+
when 'rename_column'
|
53
|
+
model = model.tableize
|
54
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{model}_#{from}_to_#{to}"
|
55
|
+
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end"
|
56
|
+
when 'alter_column'
|
57
|
+
model = model.tableize
|
58
|
+
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}"
|
59
|
+
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end"
|
60
|
+
when 'move'
|
61
|
+
# do nothing
|
36
62
|
else
|
37
|
-
|
38
|
-
when 'create_model'
|
39
|
-
columns = column.split(' ').compact
|
40
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_model model, columns
|
41
|
-
when 'remove_model'
|
42
|
-
model = model.tableize
|
43
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "drop_#{model}"
|
44
|
-
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n drop_table :#{model}\n end"
|
45
|
-
when 'rename_model'
|
46
|
-
_model, from, to = from.tableize, to.tableize, model.tableize
|
47
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{from}_to_#{to}"
|
48
|
-
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_table :#{from}, :#{to}\n end"
|
49
|
-
when 'add_column'
|
50
|
-
model = model.tableize
|
51
|
-
name_and_type = column.scan(/(.*)\((.*?)\)/).first
|
52
|
-
name, type = name_and_type[0], name_and_type[1]
|
53
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"]
|
54
|
-
when 'rename_column'
|
55
|
-
model = model.tableize
|
56
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{model}_#{from}_to_#{to}"
|
57
|
-
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end"
|
58
|
-
when 'alter_column'
|
59
|
-
model = model.tableize
|
60
|
-
generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}"
|
61
|
-
gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end"
|
62
|
-
else
|
63
|
-
raise "unexpected action: #{action}"
|
64
|
-
end
|
65
|
-
Erd::Migrator.run_migrations :up => generated_migration_file
|
66
|
-
executed_migrations << generated_migration_file
|
63
|
+
raise "unexpected action: #{action}"
|
67
64
|
end
|
65
|
+
|
66
|
+
Erd::Migrator.run_migrations :up => generated_migration_file
|
67
|
+
executed_migrations << generated_migration_file
|
68
68
|
rescue ::Erd::MigrationError => e
|
69
69
|
failed_migrations << e.message
|
70
70
|
end
|
@@ -79,28 +79,70 @@ module Erd
|
|
79
79
|
end
|
80
80
|
|
81
81
|
private
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
82
|
+
|
83
|
+
def saved_positions
|
84
|
+
if POSITIONS_JSON_FILE.exist?
|
85
|
+
ActiveSupport::JSON.decode(POSITIONS_JSON_FILE.read)
|
86
|
+
elsif OLD_POSITIONS_JSON_FILE.exist?
|
87
|
+
ActiveSupport::JSON.decode(OLD_POSITIONS_JSON_FILE.read)
|
88
|
+
else
|
89
|
+
{}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_plain
|
94
|
+
if Rails.respond_to?(:autoloaders) && Rails.autoloaders.try(:zeitwerk_enabled?)
|
95
|
+
Zeitwerk::Loader.eager_load_all
|
96
|
+
else
|
97
|
+
Rails.application.eager_load!
|
98
|
+
end
|
99
|
+
ar_descendants = ActiveRecord::Base.descendants.reject {|m| m.name.in?(%w(ActiveRecord::SchemaMigration ActiveRecord::InternalMetadata ApplicationRecord)) }
|
100
|
+
ar_descendants.reject! {|m| !m.table_exists? }
|
101
|
+
|
102
|
+
g = GraphViz.new('ERD', :type => :digraph, :rankdir => 'LR', :labelloc => :t, :ranksep => '1.5', :nodesep => '1.8', :margin => '0,0', :splines => 'spline') {|g|
|
103
|
+
nodes = ar_descendants.each_with_object({}) do |model, hash|
|
104
|
+
next if model.name.start_with? 'HABTM_'
|
105
|
+
hash[model.name] = model.columns.reject {|c| c.name.in? %w(id created_at updated_at) }.map {|c| [c.name, c.type]}
|
106
|
+
end
|
107
|
+
|
108
|
+
edges = []
|
109
|
+
ar_descendants.each do |model|
|
110
|
+
model.reflect_on_all_associations.each do |reflection|
|
111
|
+
next unless nodes.key? model.name
|
112
|
+
next if reflection.macro == :belongs_to
|
113
|
+
next unless nodes.key?(reflection.klass.name)
|
114
|
+
|
115
|
+
edges << [model.name, reflection.klass.name]
|
116
|
+
# don't include the FKs in the diagram
|
117
|
+
nodes[reflection.klass.name].delete_if {|col, _type| col == reflection.foreign_key }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
nodes.each_pair do |model_name, cols|
|
122
|
+
g.add_nodes model_name, 'shape' => 'record', 'label' => "#{model_name}|#{cols.map {|name, type| "#{name}(#{type})"}.join('\l')}"
|
95
123
|
end
|
124
|
+
edges.each do |from, to|
|
125
|
+
g.add_edge g.search_node(from), g.search_node(to)
|
126
|
+
end
|
127
|
+
}
|
128
|
+
g.output('plain' => String)
|
129
|
+
end
|
130
|
+
|
131
|
+
def render_plain(plain, positions, edit_mode = false)
|
132
|
+
_scale, svg_width, svg_height = plain.scan(/\Agraph ([\d\.]+) ([\d\.]+) ([\d\.]+)$/).first
|
133
|
+
# node name x y width height label style shape color fillcolor
|
134
|
+
models = plain.scan(/^node ([^ ]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([^ ]+) [^ ]+ [^ ]+ [^ ]+ [^ ]+\n/m).map {|model_name, x, y, width, height, label|
|
135
|
+
columns = label.gsub("\\\n", '').split('|')[1].split('\l').map {|name_and_type| name_and_type.scan(/(.*?)\((.*?)\)/).first }.map {|n, t| {:name => n, :type => t} }
|
96
136
|
custom_x, custom_y = positions[model_name.tableize].try(:split, ',')
|
97
|
-
|
98
|
-
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
|
99
|
-
h
|
137
|
+
{: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}
|
100
138
|
}.compact
|
139
|
+
max_model_x = models.map {|m| m[:x].to_f + m[:width].to_f }.max
|
140
|
+
erd_width = [[(BigDecimal(svg_width) * 72).round, max_model_x].min + 150, 1024].max
|
141
|
+
max_model_y = models.map {|m| m[:y].to_f + m[:height].to_f }.max
|
142
|
+
erd_height = [[(BigDecimal(svg_height) * 72).round, max_model_y].min + 150, 768].max
|
101
143
|
# edge tail head n x1 y1 .. xn yn [label xl yl] style color
|
102
|
-
edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from
|
103
|
-
render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width =>
|
144
|
+
edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from, :to => to}}
|
145
|
+
render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => erd_width, :height => erd_height, :models => models, :edges => edges, :edit_mode => edit_mode}
|
104
146
|
end
|
105
147
|
|
106
148
|
def gsub_file(path, flag, *args, &block)
|
@@ -2,12 +2,16 @@
|
|
2
2
|
<table>
|
3
3
|
<tr>
|
4
4
|
<td>
|
5
|
-
<span class="column_name_text"><%= column[:name] %></span>
|
6
|
-
|
5
|
+
<span class="column_name_text<%= "#{' edit' if edit_mode}" %>"><%= column[:name] %></span>
|
6
|
+
<% if edit_mode %>
|
7
|
+
<form class="rename_column_form"><span><input name="model" type="hidden" value="<%= model[:model] %>" /><input name="column" type="hidden" value="<%= column[:name] %>" /><input name="to" type="text" /><input type="submit" value="Change" /></span><a href="#!" class="cancel">Cancel</a></form>
|
8
|
+
<% end %>
|
7
9
|
</td>
|
8
10
|
<td>
|
9
|
-
<span class="column_type_text <%= column[:type]
|
10
|
-
|
11
|
+
<span class="column_type_text <%= column[:type] %><%= "#{' edit' if edit_mode}" %>"><%= column[:type] %></span>
|
12
|
+
<% if edit_mode %>
|
13
|
+
<form class="alter_column_form"><span><input name="model" type="hidden" value="<%= model[:model] %>" /><input name="column" type="hidden" value="<%= column[:name] %>" /><input name="type" type="hidden" value="<%= column[:type] %>" /><input name="to" type="text" /><input type="submit" value="Change" /></span><a href="#!" class="cancel">Cancel</a></form>
|
14
|
+
<% end %>
|
11
15
|
</td>
|
12
16
|
</tr>
|
13
17
|
</table>
|
@@ -1,28 +1,34 @@
|
|
1
1
|
<div id="erd-<%= model[:model] %>" class="model" style="top: <%= model[:y] %>px; left: <%= model[:x] %>px;" data-model_name="<%= model[:model] %>">
|
2
|
-
|
3
|
-
|
2
|
+
<% if edit_mode %>
|
3
|
+
<a href="#!" class="close"><%= image_tag '/erd/close.png' %></a>
|
4
|
+
<% end %>
|
5
|
+
<div class="model_name<%= "#{' edit' if edit_mode}" %>">
|
4
6
|
<div class="model_name_text"><%= model[:model] %></div>
|
5
|
-
|
6
|
-
<
|
7
|
-
<
|
8
|
-
<
|
9
|
-
<
|
10
|
-
|
11
|
-
|
12
|
-
<
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
7
|
+
<% if edit_mode %>
|
8
|
+
<form class="rename_model_form">
|
9
|
+
<table>
|
10
|
+
<tr>
|
11
|
+
<td>
|
12
|
+
<input name="model" type="hidden" value="<%= model[:model] %>"/>
|
13
|
+
</td>
|
14
|
+
<td>
|
15
|
+
<input name="to" type="text" /><input type="submit" value="Change"/>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
</table>
|
19
|
+
<a href="#!" class="cancel">Cancel</a>
|
20
|
+
</form>
|
21
|
+
<% end %>
|
18
22
|
</div>
|
19
23
|
<div class="columns">
|
20
24
|
<ul>
|
21
|
-
<%= render :partial => 'erd/erd/column', :collection => model[:columns], :locals => {:model => model} -%>
|
25
|
+
<%= render :partial => 'erd/erd/column', :collection => model[:columns], :locals => {:model => model, :edit_mode => edit_mode} -%>
|
22
26
|
</ul>
|
23
27
|
</div>
|
24
28
|
<div class="add_column_box">
|
25
|
-
|
29
|
+
<% if edit_mode %>
|
30
|
+
<a href="#!" class="add_column">add column</a>
|
31
|
+
<% end %>
|
26
32
|
<form class="add_column_form">
|
27
33
|
<input name="model" type="hidden" value="<%= model[:model] %>" />
|
28
34
|
<table>
|
@@ -0,0 +1,87 @@
|
|
1
|
+
<div id="erd_box">
|
2
|
+
<div id="erd_container">
|
3
|
+
<%=raw @erd %>
|
4
|
+
</div>
|
5
|
+
<div id="open_migration"><%= image_tag '/erd/angle-left.png' %></div>
|
6
|
+
<div id="migration">
|
7
|
+
<div id="close_migration"><%= image_tag '/erd/angle-right.png' %></div>
|
8
|
+
<%- if flash[:executed_migrations].present? -%>
|
9
|
+
<div id="executed">
|
10
|
+
<h2>Successfully executed following <%= flash[:executed_migrations].values.flatten.count %> migrations!</h2>
|
11
|
+
<%- [:up, :down].each do |direction| -%>
|
12
|
+
<%- if flash[:executed_migrations][direction].present? -%>
|
13
|
+
<h3><%= direction %></h3>
|
14
|
+
<ul>
|
15
|
+
<%- flash[:executed_migrations][direction].each do |m| -%>
|
16
|
+
<li><%= File.basename m.to_s %></li>
|
17
|
+
<%- end -%>
|
18
|
+
</ul>
|
19
|
+
<%- end -%>
|
20
|
+
<%- end -%>
|
21
|
+
</div>
|
22
|
+
<%- end -%>
|
23
|
+
<%- if flash[:failed_migrations].present? -%>
|
24
|
+
<div id="failed">
|
25
|
+
<h2>failed migrations</h2>
|
26
|
+
<ul>
|
27
|
+
<%- flash[:failed_migrations].each do |m| -%>
|
28
|
+
<li><%= m %></li>
|
29
|
+
<%- end -%>
|
30
|
+
</ul>
|
31
|
+
</div>
|
32
|
+
<%- end -%>
|
33
|
+
<table id="changes">
|
34
|
+
<caption>schema changes</caption>
|
35
|
+
<thead><tr><th>action</th><th>model</th><th>column</th><th>from</th><th>to</th></tr></thead>
|
36
|
+
<tbody></tbody>
|
37
|
+
</table>
|
38
|
+
<%= form_tag '/erd', :method => :put, :id => 'changes_form' do %>
|
39
|
+
<%= hidden_field_tag 'changes' %>
|
40
|
+
<%= hidden_field_tag 'position_changes' %>
|
41
|
+
<%= submit_tag 'save changes' %>
|
42
|
+
<% end %>
|
43
|
+
<%= form_tag '/erd/migrate', :method => :put, :id => 'migrate_form' do %>
|
44
|
+
<ul id="open_buttons">
|
45
|
+
<li><button id="open_up" type="button">up</button></li>
|
46
|
+
<li><button id="open_down" type="button">down</button></li>
|
47
|
+
<li><button id="close_all" type="button">close</button></li>
|
48
|
+
</ul>
|
49
|
+
<table id="migration_status">
|
50
|
+
<caption>migration status</caption>
|
51
|
+
<thead>
|
52
|
+
<tr><th class="status">status</th><th class="version">version</th><th class="name">name</th></tr>
|
53
|
+
<tr><td colspan="3" class="migrations">
|
54
|
+
<button>UNFOLD ALL</button>
|
55
|
+
<%= @migrations.count %> migrations in total (up: <%= @migrations.count {|m| m[:status] == 'up'} %>, down: <%= @migrations.count {|m| m[:status] == 'down'} %>)
|
56
|
+
</td></tr>
|
57
|
+
</thead>
|
58
|
+
<tbody>
|
59
|
+
<%- @migrations.each do |m| -%>
|
60
|
+
<tr class="<%= m[:status] %>">
|
61
|
+
<td><label><%= check_box_tag (m[:status] == 'up' ? 'down[]' : 'up[]'), m[:filename], false, :id => "check_#{m[:filename]}" %><%= m[:status] %></label></td>
|
62
|
+
<td><%= m[:version] %></td>
|
63
|
+
<td class="migration_file_name"><%= m[:name] %></td>
|
64
|
+
</tr>
|
65
|
+
<%- end -%>
|
66
|
+
</tbody>
|
67
|
+
</table>
|
68
|
+
<%= submit_tag 'run migrations' %>
|
69
|
+
<% end %>
|
70
|
+
</div>
|
71
|
+
<a href="#" id='open_create_model_dialog'%>Create Model</a>
|
72
|
+
<div id="create_model_form">
|
73
|
+
<form>
|
74
|
+
Model Name: <input id="new_model_name" name="new_model_name" type="text" /><br>
|
75
|
+
<table id="create_model_table">
|
76
|
+
<tbody>
|
77
|
+
<tr>
|
78
|
+
<td><input name="new_model_column_name_1" type="text" /></td>
|
79
|
+
<td class="separator">:</td>
|
80
|
+
<td><input name="new_model_column_type_1" type="text" value="string" /></td>
|
81
|
+
</tr>
|
82
|
+
</tbody>
|
83
|
+
</table>
|
84
|
+
<div><a href="#" id="new_model_add_column" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Add More Column</span></a></div>
|
85
|
+
</form>
|
86
|
+
</div>
|
87
|
+
</div>
|