erd 0.6.4 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 614e01232d2efeca93c7bed35a751e25a9ee991e2f51e80e171f918fc7f243ef
4
- data.tar.gz: 357077faae8695c34f34fda83f3f4437c95b1725d452c4b262cfbf68648edf28
3
+ metadata.gz: 1e9b918036131dd6376ed19adf3f6533b6caf0987a87f78b04944881ec579695
4
+ data.tar.gz: 591899522e0d2247e5bb999c88c182baeee7a90912f6f8c946bb044e83142a13
5
5
  SHA512:
6
- metadata.gz: 07a9c92343e1d277fbe84f944f08c8d3adb7ae1e166bd04b59606d7325ed25adb2c60f03aee27696e8bda48fc56ba182fde0a31cb0110aa19ad81a41ea608285
7
- data.tar.gz: 15f84992ff7fc3d83cf3df98902afaa22df912ea860345755dd21b06a7521c2d86b2a997d14ebd2cb2d59594ebf211f72271f0375b766c6bc526a58f84518144
6
+ metadata.gz: 36353f77def4b6e65e4e565c87be9a9838dbc11c5e86475aada0435d8062a010c3a683c430bf9b1620289ebddfca5ea871ffbb4f7a4fa384402451489e5590ef
7
+ data.tar.gz: 175f0d4f165dd2fa3148865e4cfc898dbae572da4c200b1b68bb6cbf9450f4b01247ccfe5e189e6e34a8dbba7216d3291285f2464b24a01e67c0fa2b4a20c31b
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 7.0, 6.1, 6.0, 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.
@@ -6,62 +6,65 @@ 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
- plain = generate_plain
11
- positions = if (json = Rails.root.join('tmp/erd_positions.json')).exist?
12
- ActiveSupport::JSON.decode json.read
13
- else
14
- {}
15
- end
16
- @erd = render_plain plain, positions
13
+ @erd = render_plain generate_plain, saved_positions
14
+ end
17
15
 
16
+ def edit
17
+ @erd = render_plain generate_plain, saved_positions, true
18
18
  @migrations = Erd::Migrator.status
19
19
  end
20
20
 
21
21
  def update
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
+
22
29
  changes = params[:changes].present? ? ActiveSupport::JSON.decode(params[:changes]) : []
23
30
  executed_migrations, failed_migrations = [], []
24
31
  changes.each do |row|
25
32
  begin
26
33
  action, model, column, from, to = row['action'], row['model'], row['column'], row['from'], row['to']
27
- if action == 'move'
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'
40
+ model = model.tableize
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'
28
48
  model = model.tableize
29
- json_file = Rails.root.join('tmp', 'erd_positions.json')
30
- positions = json_file.exist? ? ActiveSupport::JSON.decode(json_file.read) : {}
31
- positions[model] = to
32
- json_file.open('w') {|f| f.write positions.to_json}
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
33
62
  else
34
- case action
35
- when 'create_model'
36
- columns = column.split(' ').compact
37
- generated_migration_file = Erd::GenaratorRunner.execute_generate_model model, columns
38
- when 'remove_model'
39
- model = model.tableize
40
- generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "drop_#{model}"
41
- gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n drop_table :#{model}\n end"
42
- when 'rename_model'
43
- _model, from, to = from.tableize, to.tableize, model.tableize
44
- generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{from}_to_#{to}"
45
- gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_table :#{from}, :#{to}\n end"
46
- when 'add_column'
47
- model = model.tableize
48
- name_and_type = column.scan(/(.*)\((.*?)\)/).first
49
- name, type = name_and_type[0], name_and_type[1]
50
- generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"]
51
- when 'rename_column'
52
- model = model.tableize
53
- generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "rename_#{model}_#{from}_to_#{to}"
54
- gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end"
55
- when 'alter_column'
56
- model = model.tableize
57
- generated_migration_file = Erd::GenaratorRunner.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}"
58
- gsub_file generated_migration_file, /def (up|change).* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end"
59
- else
60
- raise "unexpected action: #{action}"
61
- end
62
- Erd::Migrator.run_migrations :up => generated_migration_file
63
- executed_migrations << generated_migration_file
63
+ raise "unexpected action: #{action}"
64
64
  end
65
+
66
+ Erd::Migrator.run_migrations :up => generated_migration_file
67
+ executed_migrations << generated_migration_file
65
68
  rescue ::Erd::MigrationError => e
66
69
  failed_migrations << e.message
67
70
  end
@@ -77,6 +80,16 @@ module Erd
77
80
 
78
81
  private
79
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
+
80
93
  def generate_plain
81
94
  if Rails.respond_to?(:autoloaders) && Rails.autoloaders.try(:zeitwerk_enabled?)
82
95
  Zeitwerk::Loader.eager_load_all
@@ -115,20 +128,21 @@ module Erd
115
128
  g.output('plain' => String)
116
129
  end
117
130
 
118
- def render_plain(plain, positions)
131
+ def render_plain(plain, positions, edit_mode = false)
119
132
  _scale, svg_width, svg_height = plain.scan(/\Agraph ([\d\.]+) ([\d\.]+) ([\d\.]+)$/).first
120
133
  # node name x y width height label style shape color fillcolor
121
- max_model_x, max_model_y = 0, 0
122
134
  models = plain.scan(/^node ([^ ]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([\d\.]+) ([^ ]+) [^ ]+ [^ ]+ [^ ]+ [^ ]+\n/m).map {|model_name, x, y, width, height, label|
123
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} }
124
136
  custom_x, custom_y = positions[model_name.tableize].try(:split, ',')
125
- 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}
126
- 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
127
- 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}
128
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].compact.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].compact.min + 150, 768].max
129
143
  # edge tail head n x1 y1 .. xn yn [label xl yl] style color
130
144
  edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from, :to => to}}
131
- 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}
145
+ render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => erd_width, :height => erd_height, :models => models, :edges => edges, :edit_mode => edit_mode}
132
146
  end
133
147
 
134
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
- <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>
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] %>"><%= column[:type] %></span>
10
- <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>
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
- <a href="#!" class="close"><%= image_tag '/erd/close.png' %></a>
3
- <div class="model_name">
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
- <form class="rename_model_form">
6
- <table>
7
- <tr>
8
- <td>
9
- <input name="model" type="hidden" value="<%= model[:model] %>"/>
10
- </td>
11
- <td>
12
- <input name="to" type="text" /><input type="submit" value="Change"/>
13
- </td>
14
- </tr>
15
- </table>
16
- <a href="#!" class="cancel">Cancel</a>
17
- </form>
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
- <a href="#!" class="add_column">add column</a>
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>
@@ -1,4 +1,4 @@
1
1
  <div id="erd" data-svg_width="<%= width %>" data-svg_height="<%= height %>">
2
- <%= render :partial => 'erd/erd/model', :collection => models -%>
2
+ <%= render :partial => 'erd/erd/model', :collection => models, :locals => {:edit_mode => edit_mode} -%>
3
3
  <script>window.raw_edges = <%= edges.to_json.html_safe %>;</script>
4
4
  </div>
@@ -2,85 +2,16 @@
2
2
  <div id="erd_container">
3
3
  <%=raw @erd %>
4
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
- <%= submit_tag 'save changes' %>
41
- <% end %>
42
- <%= form_tag '/erd/migrate', :method => :put, :id => 'migrate_form' do %>
43
- <ul id="open_buttons">
44
- <li><button id="open_up" type="button">up</button></li>
45
- <li><button id="open_down" type="button">down</button></li>
46
- <li><button id="close_all" type="button">close</button></li>
47
- </ul>
48
- <table id="migration_status">
49
- <caption>migration status</caption>
50
- <thead>
51
- <tr><th class="status">status</th><th class="version">version</th><th class="name">name</th></tr>
52
- <tr><td colspan="3" class="migrations">
53
- <button>UNFOLD ALL</button>
54
- <%= @migrations.count %> migrations in total (up: <%= @migrations.count {|m| m[:status] == 'up'} %>, down: <%= @migrations.count {|m| m[:status] == 'down'} %>)
55
- </td></tr>
56
- </thead>
57
- <tbody>
58
- <%- @migrations.each do |m| -%>
59
- <tr class="<%= m[:status] %>">
60
- <td><label><%= check_box_tag (m[:status] == 'up' ? 'down[]' : 'up[]'), m[:filename] %><%= m[:status] %></label></td>
61
- <td><%= m[:version] %></td>
62
- <td class="migration_file_name"><%= m[:name] %></td>
63
- </tr>
64
- <%- end -%>
65
- </tbody>
66
- </table>
67
- <%= submit_tag 'run migrations' %>
68
- <% end %>
69
- </div>
70
- <a href="#" id='open_create_model_dialog'%>Create Model</a>
71
- <div id="create_model_form">
72
- <form>
73
- Model Name: <input id="new_model_name" name="new_model_name" type="text" /><br>
74
- <table id="create_model_table">
75
- <tbody>
76
- <tr>
77
- <td><input name="new_model_column_name_1" type="text" /></td>
78
- <td class="separator">:</td>
79
- <td><input name="new_model_column_type_1" type="text" value="string" /></td>
80
- </tr>
81
- </tbody>
82
- </table>
83
- <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>
84
- </form>
85
- </div>
5
+ <%= form_tag '/erd', :method => :put, :id => 'changes_form' do %>
6
+ <%= hidden_field_tag 'position_changes' %>
7
+ <% end %>
8
+ <input id="drawer_switch" type="checkbox">
9
+ <label id="drawer_hide_label" class="drawer_switch_label" for="drawer_switch">&gt;&nbsp;&nbsp;Hide Buttons</label>
10
+ <label id="drawer_show_label" class="drawer_switch_label" for="drawer_switch">&lt;</label>
11
+ <nav id="buttons">
12
+ <ul>
13
+ <li><a href="#!" id="save_position_changes" class="menu_button">Save Position Changes</a></li>
14
+ <li><%= link_to 'Edit the Database', :edit, :id => 'link_to_edit', :class => 'menu_button' %></li>
15
+ </ul>
16
+ </nav>
86
17
  </div>
@@ -2,7 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta charset='utf-8'>
5
- <title>ERD - <%= Rails.application.class.parent.name %></title>
5
+ <title>ERD - <%= Rails.application.class.name[/[^:]+/] %></title>
6
6
  <%= stylesheet_link_tag '/erd/erd', :media => 'all' %>
7
7
  <%= stylesheet_link_tag 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css', :media => 'all' %>
8
8
  <%= javascript_include_tag 'https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js' %>
data/config/routes.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  Erd::Engine.routes.draw do
4
4
  get '/' => 'erd#index'
5
+ get 'edit' => 'erd#edit'
5
6
  put '/' => 'erd#update'
6
7
  put '/migrate' => 'erd#migrate', :as => 'migrate'
7
8
  root :to => 'erd#index'
data/erd.gemspec CHANGED
@@ -11,9 +11,9 @@ Gem::Specification.new do |gem|
11
11
  gem.homepage = 'https://github.com/amatsuda/erd'
12
12
  gem.license = 'MIT'
13
13
 
14
- gem.files = `git ls-files`.split($\)
15
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.files = Dir.chdir(File.expand_path(__dir__)) do
15
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
16
+ end
17
17
  gem.name = 'erd'
18
18
  gem.require_paths = ['lib']
19
19
  gem.version = Erd::VERSION
data/lib/erd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Erd
4
- VERSION = '0.6.4'
4
+ VERSION = '0.8.1'
5
5
  end
data/public/erd/erd.css CHANGED
@@ -219,8 +219,9 @@ li {
219
219
  box-shadow: rgba(0, 0, 0, 0.7) 0 2px 2px; }
220
220
  #erd .model .model_name {
221
221
  border-bottom: 1px #444444 solid;
222
- cursor: pointer;
223
222
  margin: 1px 5px 0 5px auto; }
223
+ #erd .model .model_name.edit {
224
+ cursor: pointer; }
224
225
  #erd .model .model_name .model_name_text {
225
226
  text-align: center;
226
227
  display: block;
@@ -229,10 +230,10 @@ li {
229
230
  background: -ms-linear-gradient(top, #eeeeee 0%, #d0d0d0 88%);
230
231
  background: -o-linear-gradient(top, #eeeeee 0%, #d0d0d0 88%);
231
232
  background: linear-gradient(top, #eeeeee 0%, #d0d0d0 88%);
232
- font-size: 13px;
233
+ font-size: 15px;
233
234
  font-weight: bold;
234
235
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
235
- line-height: 2.2;
236
+ line-height: 1.6;
236
237
  padding: 0 0.8em; }
237
238
  #erd .model .model_name .model_name_text.unsaved {
238
239
  background: #fffebe;
@@ -314,7 +315,7 @@ li {
314
315
  font-size: small;
315
316
  display: block;
316
317
  padding: 0 5px;
317
- line-height: 2;
318
+ line-height: 1.6;
318
319
  background: #444444;
319
320
  color: white;
320
321
  text-decoration: none; }
@@ -328,9 +329,9 @@ li {
328
329
 
329
330
  .columns .column {
330
331
  border-bottom: dotted 1px #cccccc;
331
- padding: 0 0.8em;
332
+ padding: 0 0.5em;
332
333
  clear: both;
333
- line-height: 28px;
334
+ line-height: 20px;
334
335
  font-size: 14px; }
335
336
  .columns .column table {
336
337
  width: 100%; }
@@ -338,12 +339,12 @@ li {
338
339
  background: #f9f9f9; }
339
340
  .columns .column:last-child {
340
341
  border-bottom: none; }
341
- .columns .column .column_name_text,
342
- .columns .column .column_type_text {
342
+ .columns .column .column_name_text.edit,
343
+ .columns .column .column_type_text.edit {
343
344
  cursor: pointer; }
344
345
  .columns .column .column_name_text {
345
346
  margin: 0 1.4em 0 0; }
346
- .columns .column .column_name_text:hover {
347
+ .columns .column .column_name_text.edit:hover {
347
348
  text-decoration: underline; }
348
349
  .columns .column.unsaved {
349
350
  background: #fffebe;
@@ -377,11 +378,11 @@ li {
377
378
  .columns .column .rename_column_form {
378
379
  padding: 8px; }
379
380
  .columns .column .column_type_text {
380
- font-size: 10px;
381
+ font-size: 13px;
381
382
  float: right;
382
383
  display: block;
383
384
  line-height: 16px;
384
- margin: 5px 0 0;
385
+ margin: 1px 0 0;
385
386
  -webkit-border-radius: 4px;
386
387
  -moz-border-radius: 4px;
387
388
  -ms-border-radius: 4px;
@@ -395,7 +396,7 @@ li {
395
396
  background: #f9eee9;
396
397
  color: #444444;
397
398
  border-style: solid; }
398
- .columns .column .column_type_text:hover {
399
+ .columns .column .column_type_text.edit:hover {
399
400
  border-color: #e36c33;
400
401
  background: #edd0c2; }
401
402
  .columns .column .column_type_text.date, .columns .column .column_type_text.time, .columns .column .column_type_text.timestamp, .columns .column .column_type_text.datetime {
@@ -403,7 +404,7 @@ li {
403
404
  background: #f3e2e4;
404
405
  color: #444444;
405
406
  border-style: solid; }
406
- .columns .column .column_type_text.date:hover, .columns .column .column_type_text.time:hover, .columns .column .column_type_text.timestamp:hover, .columns .column .column_type_text.datetime:hover {
407
+ .columns .column .column_type_text.edit.date:hover, .columns .column .column_type_text.edit.time:hover, .columns .column .column_type_text.edit.timestamp:hover, .columns .column .column_type_text.edit.datetime:hover {
407
408
  border-color: #d0394d;
408
409
  background: #e4bec3; }
409
410
  .columns .column .column_type_text.boolean {
@@ -411,7 +412,7 @@ li {
411
412
  background: #c7dce6;
412
413
  color: #444444;
413
414
  border-style: solid; }
414
- .columns .column .column_type_text.boolean:hover {
415
+ .columns .column .column_type_text.edit.boolean:hover {
415
416
  border-color: #2e87b3;
416
417
  background: #a3c6d7; }
417
418
  .columns .column .column_type_text.text {
@@ -419,7 +420,7 @@ li {
419
420
  background: #efe7d3;
420
421
  color: #444444;
421
422
  border-style: solid; }
422
- .columns .column .column_type_text.text:hover {
423
+ .columns .column .column_type_text.edit.text:hover {
423
424
  border-color: #cb9d2b;
424
425
  background: #e1d2ae; }
425
426
  .columns .column .column_type_text.decimal {
@@ -427,7 +428,7 @@ li {
427
428
  background: #dfdf50;
428
429
  color: #444444;
429
430
  border-style: solid; }
430
- .columns .column .column_type_text.decimal:hover {
431
+ .columns .column .column_type_text.edit.decimal:hover {
431
432
  border-color: #5e5e05;
432
433
  background: #d5d527; }
433
434
  .columns .column .column_type_text.float {
@@ -435,7 +436,7 @@ li {
435
436
  background: silver;
436
437
  color: #444444;
437
438
  border-style: solid; }
438
- .columns .column .column_type_text.float:hover {
439
+ .columns .column .column_type_text.edit.float:hover {
439
440
  border-color: #684b53;
440
441
  background: #a6a6a6; }
441
442
  .columns .column .column_type_text.integer {
@@ -443,7 +444,7 @@ li {
443
444
  background: #dfdfe0;
444
445
  color: #444444;
445
446
  border-style: solid; }
446
- .columns .column .column_type_text.integer:hover {
447
+ .columns .column .column_type_text.edit.integer:hover {
447
448
  border-color: #606493;
448
449
  background: #c5c5c7; }
449
450
  .columns .column .column_type_text.primary_key {
@@ -451,7 +452,7 @@ li {
451
452
  background: #f9efe7;
452
453
  color: #444444;
453
454
  border-style: solid; }
454
- .columns .column .column_type_text.primary_key:hover {
455
+ .columns .column .column_type_text.edit.primary_key:hover {
455
456
  border-color: #e47e30;
456
457
  background: #eed3bf; }
457
458
  .columns .column .column_type_text.string {
@@ -459,7 +460,7 @@ li {
459
460
  background: #d3e09e;
460
461
  color: #444444;
461
462
  border-style: solid; }
462
- .columns .column .column_type_text.string:hover {
463
+ .columns .column .column_type_text.edit.string:hover {
463
464
  border-color: #7f9919;
464
465
  background: #c1d477; }
465
466
  .columns .column .column_type_text.unsaved {
@@ -510,6 +511,54 @@ li {
510
511
  #model_name_changes, #column_name_changes {
511
512
  display: none; }
512
513
 
514
+ #drawer_switch {
515
+ display: none; }
516
+ #drawer_switch:checked ~ #buttons {
517
+ right: -400px; }
518
+ #drawer_switch:checked ~ #drawer_hide_label {
519
+ visibility: hidden; }
520
+ #drawer_switch:checked ~ #drawer_show_label {
521
+ visibility: visible; }
522
+
523
+ #buttons {
524
+ position: fixed;
525
+ top: 70px;
526
+ right: 15px;
527
+ -webkit-transition: all 0.5s;
528
+ transition: all 0.5s; }
529
+
530
+ .drawer_switch_label {
531
+ position: fixed;
532
+ right: 15px;
533
+ top: 10px;
534
+ background: rgba(0, 0, 0, 0.6);
535
+ padding: 12px 20px;
536
+ color: white;
537
+ cursor: pointer;
538
+ text-decoration: none;
539
+ font-size: 13px; }
540
+ .drawer_switch_label:hover {
541
+ background: rgba(0, 0, 0, 0.8); }
542
+ #drawer_show_label {
543
+ visibility: hidden; }
544
+
545
+ .menu_button {
546
+ position: relative;
547
+ right: 0;
548
+ background: rgba(0, 0, 0, 0.6);
549
+ padding: 12px 20px;
550
+ color: white;
551
+ text-decoration: none;
552
+ font-size: 13px; }
553
+ .menu_button:hover {
554
+ background: rgba(0, 0, 0, 0.8); }
555
+ #save_position_changes {
556
+ visibility: hidden;
557
+ top: 70px;
558
+ background: rgba(191, 0, 0, 0.6); }
559
+ #save_position_changes:hover {
560
+ background: rgba(191, 0, 0, 0.8); }
561
+
513
562
  #open_create_model_dialog {
514
563
  position: fixed;
515
564
  right: 15px;
data/public/erd/erd.js CHANGED
@@ -19,10 +19,12 @@ class ERD {
19
19
  this.handle_new_model_add_column_click = this.handle_new_model_add_column_click.bind(this);
20
20
  this.handle_open_migration_click = this.handle_open_migration_click.bind(this);
21
21
  this.handle_close_migration_click = this.handle_close_migration_click.bind(this);
22
+ this.handle_save_position_changes_click = this.handle_save_position_changes_click.bind(this);
22
23
  this.name = name;
23
24
  this.elem = elem;
24
25
  this.edges = edges;
25
26
  this.paper = Raphael(this.name, this.elem.data('svg_width'), this.elem.data('svg_height'));
27
+ this.position_changes = {};
26
28
  this.setup_handlers();
27
29
  const models = this.elem.find('.model');
28
30
  this.models = {};
@@ -122,11 +124,13 @@ class ERD {
122
124
  const from = target.data('original_position');
123
125
  const to = [target.css('left').replace(/px$/, ''), target.css('top').replace(/px$/, '')].join();
124
126
  this.upsert_change('move', model_name, '', '', to);
127
+ this.position_changes[model_name] = to;
125
128
  this.connect_arrows(this.edges.filter(e=> (e.from === model_name) || (e.to === model_name)));
129
+ document.getElementById("save_position_changes").style.visibility = "visible";
126
130
  }
127
131
 
128
132
  setup_click_handlers() {
129
- $('div.model_name_text, span.column_name_text, span.column_type_text').on('click', this.handle_text_elem_click);
133
+ $('div.model_name_text.edit, span.column_name_text.edit, span.column_type_text.edit').on('click', this.handle_text_elem_click);
130
134
  $('div.model a.add_column').on('click', this.handle_add_column_click);
131
135
  $('div.model a.cancel').on('click', this.handle_cancel_click);
132
136
  $('div.model a.close').on('click', this.handle_remove_model_click);
@@ -134,6 +138,7 @@ class ERD {
134
138
  $('div.model a.cancel').on('click', this.handle_cancel_click);
135
139
  $('div#open_migration').on('click', this.handle_open_migration_click);
136
140
  $('div#close_migration').on('click', this.handle_close_migration_click);
141
+ $('#save_position_changes').on('click', this.handle_save_position_changes_click);
137
142
  }
138
143
 
139
144
  setup_submit_handlers() {
@@ -165,6 +170,7 @@ class ERD {
165
170
  return change;
166
171
  }).toArray();
167
172
  $('#changes_form').find('input[name=changes]').val(JSON.stringify(changes));
173
+ $('#changes_form').find('input[name=position_changes]').val(JSON.stringify(this.position_changes));
168
174
  }
169
175
 
170
176
  handle_add_column(ev) {
@@ -359,6 +365,11 @@ class ERD {
359
365
  .parent().hide()
360
366
  .prev('div').show();
361
367
  }
368
+
369
+ handle_save_position_changes_click(ev) {
370
+ $('#changes_form').find('input[name=position_changes]').val(JSON.stringify(this.position_changes));
371
+ $('#changes_form').submit();
372
+ }
362
373
  }
363
374
 
364
375
  $(function() {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akira Matsuda
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-25 00:00:00.000000000 Z
11
+ date: 2022-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-graphviz
@@ -161,12 +161,13 @@ files:
161
161
  - ".travis.yml"
162
162
  - Gemfile
163
163
  - MIT-LICENSE
164
- - README.rdoc
164
+ - README.md
165
165
  - Rakefile
166
166
  - app/controllers/erd/application_controller.rb
167
167
  - app/controllers/erd/erd_controller.rb
168
168
  - app/views/erd/erd/_column.html.erb
169
169
  - app/views/erd/erd/_model.html.erb
170
+ - app/views/erd/erd/edit.html.erb
170
171
  - app/views/erd/erd/erd.html.erb
171
172
  - app/views/erd/erd/index.html.erb
172
173
  - app/views/layouts/erd/application.html.erb
@@ -196,21 +197,11 @@ files:
196
197
  - public/erd/erd.css
197
198
  - public/erd/erd.js
198
199
  - src/assets/stylesheets/erd/erd.css.scss
199
- - test/fake_app/config/database.yml
200
- - test/fake_app/db/migrate/20120428022519_create_authors.rb
201
- - test/fake_app/db/migrate/20120428022535_create_books.rb
202
- - test/fake_app/db/schema.rb
203
- - test/fake_app/fake_app.rb
204
- - test/fake_app/log/.gitignore
205
- - test/fake_app/tmp/.gitkeep
206
- - test/features/erd_test.rb
207
- - test/lib/migrator_test.rb
208
- - test/test_helper.rb
209
200
  homepage: https://github.com/amatsuda/erd
210
201
  licenses:
211
202
  - MIT
212
203
  metadata: {}
213
- post_install_message:
204
+ post_install_message:
214
205
  rdoc_options: []
215
206
  require_paths:
216
207
  - lib
@@ -225,18 +216,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
216
  - !ruby/object:Gem::Version
226
217
  version: '0'
227
218
  requirements: []
228
- rubygems_version: 3.0.3
229
- signing_key:
219
+ rubygems_version: 3.4.0.dev
220
+ signing_key:
230
221
  specification_version: 4
231
222
  summary: erd engine on Rails
232
- test_files:
233
- - test/fake_app/config/database.yml
234
- - test/fake_app/db/migrate/20120428022519_create_authors.rb
235
- - test/fake_app/db/migrate/20120428022535_create_books.rb
236
- - test/fake_app/db/schema.rb
237
- - test/fake_app/fake_app.rb
238
- - test/fake_app/log/.gitignore
239
- - test/fake_app/tmp/.gitkeep
240
- - test/features/erd_test.rb
241
- - test/lib/migrator_test.rb
242
- - test/test_helper.rb
223
+ test_files: []
data/README.rdoc DELETED
@@ -1,66 +0,0 @@
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
- Add 'erd' gem to your existing app's Gemfile:
16
- gem 'erd'
17
-
18
- Bundle it:
19
- % bundle
20
-
21
-
22
- == Usage
23
-
24
- Browse at your http://localhost:3000/erd
25
-
26
-
27
- == Features
28
-
29
- * Erd draws an ER diagram based on your app's database and models
30
-
31
- * You can drag and arrange the positions of each model
32
-
33
- * You can operate DB schema manipulations such as `add column`, `rename column`, `alter column`, `create model (as well as table)`, and `drop table`
34
-
35
- * Then, Erd generates migration files on the server
36
-
37
- * And you can run each migration on your browser
38
-
39
-
40
- == TODO
41
-
42
- * Fix buggy JS
43
-
44
- * drop column (need to think of the UI)
45
-
46
- * stop depending on Graphviz
47
-
48
- * tests
49
-
50
- * cleaner code (the code is horrible. Please don't read the code, though of course your patches welcome)
51
-
52
-
53
- == Contributing to Erd
54
-
55
- * Send me your pull requests!
56
-
57
-
58
- == Team
59
-
60
- * {Akira Matsuda}[https://github.com/amatsuda]
61
- * {Teppei Machida}[http://github.com/machida] (design)
62
-
63
-
64
- == Copyright
65
-
66
- Copyright (c) 2012 Akira Matsuda. See MIT-LICENSE for further details.
@@ -1,3 +0,0 @@
1
- development:
2
- adapter: sqlite3
3
- database: ":memory:"
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateAuthors < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
4
- def change
5
- create_table :authors do |t|
6
- t.string :name
7
-
8
- t.timestamps
9
- end
10
- end
11
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CreateBooks < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
4
- def change
5
- create_table :books do |t|
6
- t.references :author
7
- t.string :title
8
-
9
- t.timestamps
10
- end
11
- end
12
- end
File without changes
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_record'
4
- require 'action_controller/railtie'
5
-
6
- # config
7
- module ErdApp
8
- class Application < Rails::Application
9
- # Rais.root
10
- config.root = File.dirname(__FILE__)
11
-
12
- config.secret_token = 'fall to your knees and repent if you please'
13
- config.session_store :cookie_store, :key => '_myapp_session'
14
- config.active_support.deprecation = :log
15
- config.eager_load = false
16
-
17
- config.app_generators.orm :active_record, :migration => true, :timestamps => true
18
- end
19
- end
20
- ErdApp::Application.initialize!
21
- ErdApp::Application.routes.draw {}
22
-
23
- # models
24
- class Author < ActiveRecord::Base
25
- has_many :books
26
- end
27
- class Book < ActiveRecord::Base
28
- belongs_to :author
29
- end
30
-
31
- # helpers
32
- module ApplicationHelper; end
@@ -1 +0,0 @@
1
- *.log
File without changes
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class ErdIndexTest < ActionDispatch::IntegrationTest
6
- test 'with author and book model' do
7
- visit '/erd'
8
-
9
- if Capybara::VERSION > '3'
10
- assert has_content? 'Author', :minimum => 1
11
- else
12
- assert has_content? 'Author'
13
- end
14
- assert has_content? 'name'
15
- assert has_content? 'Book'
16
- assert has_content? 'title'
17
- end
18
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class MigratorTest < ActiveSupport::TestCase
6
- teardown do
7
- Dir.glob(Rails.root.join('db/migrate/*.rb')).each do |f|
8
- FileUtils.rm f unless File.basename(f).in? %w(20120428022519_create_authors.rb 20120428022535_create_books.rb)
9
- end
10
- end
11
-
12
- sub_test_case '.status' do
13
- test 'when all migrations are up' do
14
- assert_equal [{:status => 'up', :version => '20120428022519', :name => 'create_authors', :filename => '20120428022519_create_authors.rb'}, {:status => 'up', :version => '20120428022535', :name => 'create_books', :filename => '20120428022535_create_books.rb'}], Erd::Migrator.status
15
- end
16
-
17
- test 'when one is undone' do
18
- FileUtils.touch Rails.root.join('db/migrate/20999999999999_create_foobars.rb')
19
-
20
- assert_equal [{:status => 'up', :version => '20120428022519', :name => 'create_authors', :filename => '20120428022519_create_authors.rb'}, {:status => 'up', :version => '20120428022535', :name => 'create_books', :filename => '20120428022535_create_books.rb'}, {:status => 'down', :version => '20999999999999', :name => 'create_foobars', :filename => '20999999999999_create_foobars.rb'}], Erd::Migrator.status
21
- end
22
- end
23
-
24
- sub_test_case '.run_migrations' do
25
- setup do
26
- File.open(Rails.root.join('db/migrate/20999999999999_create_foobars.rb'), 'w') do |f|
27
- f.puts 'class CreateFoobars < ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration; end'
28
- end
29
-
30
- if defined? ActiveRecord::MigrationContext # >= 5.2
31
- mock.instance_of(ActiveRecord::MigrationContext).run(:up, 20999999999999)
32
- else
33
- mock(ActiveRecord::Migrator).run(:up, ['db/migrate'], 20999999999999)
34
- end
35
- mock(ActiveRecord::SchemaDumper).dump(ActiveRecord::Base.connection, anything)
36
- end
37
- test 'runs migration by version number' do
38
- Erd::Migrator.run_migrations(:up => ['20999999999999'])
39
- end
40
- test 'runs migration by migration filename' do
41
- Erd::Migrator.run_migrations(:up => [Rails.root.join('db/migrate/20999999999999_create_foobars.rb')])
42
- end
43
- end
44
- end
45
-
46
- class GenaratorRunnerTest < ActiveSupport::TestCase
47
- setup do
48
- stub.proxy(Time).now {|t| stub(t).utc { Time.parse '2012/5/12 13:26' } }
49
- end
50
- teardown do
51
- Dir.glob(Rails.root.join('db/migrate/*.rb')).each do |f|
52
- FileUtils.rm f unless File.basename(f).in? %w(20120428022519_create_authors.rb 20120428022535_create_books.rb)
53
- end
54
- end
55
-
56
- test '.execute_generate_migration' do
57
- assert_includes Erd::GenaratorRunner.execute_generate_migration('create_foobars'), 'db/migrate/20120512132600_create_foobars.rb'
58
- end
59
- end
data/test/test_helper.rb DELETED
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
- $LOAD_PATH.unshift(File.dirname(__FILE__))
5
-
6
- ENV['RAILS_ENV'] = 'development'
7
-
8
- # load Rails first
9
- require 'rails'
10
- require 'action_controller/railtie'
11
- require 'active_record/railtie'
12
- require 'erd'
13
- require 'fake_app/fake_app'
14
- require 'test/unit/rails/test_help'
15
- Bundler.require
16
- require 'capybara'
17
- require 'selenium/webdriver'
18
-
19
- begin
20
- require "action_dispatch/system_test_case"
21
- rescue LoadError
22
- Capybara.register_driver :chrome do |app|
23
- options = Selenium::WebDriver::Chrome::Options.new(:args => %w[no-sandbox headless disable-gpu])
24
- Capybara::Selenium::Driver.new(app, :browser => :chrome, :options => options)
25
- end
26
- Capybara.javascript_driver = :chrome
27
- else
28
- ActionDispatch::SystemTestCase.driven_by(:selenium, :using => :headless_chrome)
29
- end
30
-
31
- ActiveRecord::Migration.verbose = false
32
- if defined? ActiveRecord::MigrationContext # >= 5.2
33
- ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
34
- ActiveRecord::Base.connection.migration_context.migrate
35
- else
36
- ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths.map {|p| Rails.root.join p}, nil)
37
- end