erd 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/Rakefile +9 -1
- data/app/assets/javascripts/erd/erd.js.coffee +27 -20
- data/app/assets/stylesheets/erd/erd.css.scss +40 -21
- data/app/controllers/erd/erd_controller.rb +10 -61
- data/app/views/erd/erd/_model.html.erb +1 -1
- data/app/views/erd/erd/erd.html.erb +1 -3
- data/app/views/erd/erd/index.html.erb +1 -1
- data/app/views/layouts/erd/application.html.erb +1 -0
- data/erd.gemspec +2 -2
- data/lib/erd/migrator.rb +60 -0
- data/lib/erd/railtie.rb +3 -0
- data/lib/erd/version.rb +1 -1
- data/spec/fake_app/db/migrate/20120428022519_create_authors.rb +9 -0
- data/spec/fake_app/db/migrate/20120428022535_create_books.rb +11 -0
- data/spec/{internal/public/favicon.ico → fake_app/db/schema.rb} +0 -0
- data/spec/fake_app/fake_app.rb +30 -0
- data/spec/{internal → fake_app}/log/.gitignore +0 -0
- data/spec/lib/migrator_spec.rb +42 -0
- data/spec/requests/erd_spec.rb +11 -0
- data/spec/spec_helper.rb +15 -8
- metadata +123 -86
- data/spec/controllers/erd_controller_spec.rb +0 -10
- data/spec/internal/app/models/post.rb +0 -3
- data/spec/internal/app/models/user.rb +0 -3
- data/spec/internal/config/database.yml +0 -3
- data/spec/internal/config/routes.rb +0 -3
- data/spec/internal/db/combustion_test.sqlite +0 -0
- data/spec/internal/db/schema.rb +0 -15
data/.gitignore
CHANGED
data/Rakefile
CHANGED
@@ -1,8 +1,20 @@
|
|
1
1
|
class ERD
|
2
2
|
constructor: (@name, @elem, @edges) ->
|
3
|
-
|
3
|
+
svg_width = @elem.data('svg_width')
|
4
|
+
svg_height = @elem.data('svg_height')
|
5
|
+
if (svg_width > @elem.width())
|
6
|
+
size = @elem.width() / svg_width
|
7
|
+
$('#erd > .model').each ->
|
8
|
+
left = parseFloat $(this).css('left')
|
9
|
+
top = parseFloat $(this).css('top')
|
10
|
+
$(this).css({left: left * size, top: top * size})
|
11
|
+
@paper = Raphael(name, @elem.width(), svg_height)
|
4
12
|
@setup_handlers()
|
5
|
-
@
|
13
|
+
models = @elem.find('.model')
|
14
|
+
@models = {}
|
15
|
+
for model in models
|
16
|
+
@models[$(model).data('model_name')] = model
|
17
|
+
@connect_arrows(@edges)
|
6
18
|
|
7
19
|
upsert_change: (action, model, column, from, to) ->
|
8
20
|
rows = ($(tr).find('td') for tr in $('#changes > tbody > tr'))
|
@@ -28,14 +40,16 @@ class ERD
|
|
28
40
|
[left, width, top, height] = [parseFloat(div.css('left')), parseFloat(div.css('width')), parseFloat(div.css('top')), parseFloat(div.css('height'))]
|
29
41
|
{left: left, right: left + width, top: top, bottom: top + height, center: {x: (left + left + width) / 2, y: (top + top + height) / 2}, vertex: {}}
|
30
42
|
|
31
|
-
connect_arrows:
|
32
|
-
$.each
|
33
|
-
@connect_arrow $(
|
43
|
+
connect_arrows: (edges) =>
|
44
|
+
$.each edges, (i, edge) =>
|
45
|
+
@connect_arrow edge, $(@models[edge.from]), $(@models[edge.to])
|
34
46
|
|
35
|
-
connect_arrow: (from_elem, to_elem) ->
|
47
|
+
connect_arrow: (edge, from_elem, to_elem) ->
|
36
48
|
#TODO handle self referential associations
|
37
49
|
return if from_elem.attr('id') == to_elem.attr('id')
|
38
50
|
|
51
|
+
edge.path.remove() if edge.path?
|
52
|
+
|
39
53
|
from = @positions(from_elem)
|
40
54
|
to = @positions(to_elem)
|
41
55
|
#FIXME terrible code
|
@@ -64,7 +78,7 @@ class ERD
|
|
64
78
|
else
|
65
79
|
path = "M#{Math.floor(from.vertex.x)} #{Math.floor(from.vertex.y)}V#{Math.floor((from.vertex.y + to.vertex.y) / 2)} H#{Math.floor(to.vertex.x)} V#{Math.floor(to.vertex.y)}"
|
66
80
|
|
67
|
-
@paper.path(path).attr({'stroke-width': 2, opacity: 0.5, 'arrow-end': 'classic-wide-long'})
|
81
|
+
edge.path = @paper.path(path).attr({'stroke-width': 2, opacity: 0.5, 'arrow-end': 'classic-wide-long'})
|
68
82
|
|
69
83
|
setup_handlers: ->
|
70
84
|
@setup_click_handlers()
|
@@ -74,21 +88,14 @@ class ERD
|
|
74
88
|
handle_drag: (ev, ui) =>
|
75
89
|
target = $(ev.target)
|
76
90
|
target.addClass('noclick')
|
77
|
-
|
91
|
+
model_name = target.data('model_name')
|
78
92
|
from = target.data('original_position')
|
79
93
|
to = [target.css('left').replace(/px$/, ''), target.css('top').replace(/px$/, '')].join()
|
80
|
-
@upsert_change 'move',
|
81
|
-
@
|
82
|
-
@connect_arrows(@edges)
|
94
|
+
@upsert_change 'move', model_name, '', '', to
|
95
|
+
@connect_arrows(@edges.filter((e)-> e.from == model_name || e.to == model_name))
|
83
96
|
|
84
97
|
setup_click_handlers: ->
|
85
|
-
|
86
|
-
'div.model_name_text',
|
87
|
-
'span.column_name_text',
|
88
|
-
'span.column_type_text'
|
89
|
-
].join()
|
90
|
-
|
91
|
-
$(text_elems).on 'click', @handle_text_elem_click
|
98
|
+
$('div.model_name_text, span.column_name_text, span.column_type_text').on 'click', @handle_text_elem_click
|
92
99
|
$('div.model a.add_column').on 'click', @handle_add_column_click
|
93
100
|
$('div.model a.close').on 'click', @handle_remove_model_click
|
94
101
|
|
@@ -237,12 +244,12 @@ class ERD
|
|
237
244
|
|
238
245
|
return unless confirm('remove this table?')
|
239
246
|
|
240
|
-
|
247
|
+
model_name = parent.data('model_name')
|
241
248
|
upsert_change 'remove_model', model_name, '', '', ''
|
242
249
|
parent.hide()
|
243
250
|
|
244
251
|
$.each @edges, (i, edge) =>
|
245
|
-
@edges.splice i, 1 if (edge.from ==
|
252
|
+
@edges.splice i, 1 if (edge.from == model_name) || (edge.to == model_name)
|
246
253
|
@paper.clear()
|
247
254
|
@connect_arrows(@edges)
|
248
255
|
|
@@ -1,44 +1,45 @@
|
|
1
|
-
|
1
|
+
html, body, p, ul, ol, dl, p, li, dt, dd, form {
|
2
2
|
margin: 0;
|
3
3
|
padding: 0;
|
4
4
|
}
|
5
5
|
|
6
|
-
body div {
|
7
|
-
text-align: left;
|
8
|
-
margin: 0 auto;
|
9
|
-
}
|
10
|
-
|
11
6
|
li {
|
12
7
|
list-style-type: none;
|
13
8
|
}
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
.ui-dialog .ui-state-highlight, .ui-dialog .ui-state-error { padding: 0; }
|
21
|
-
|
22
|
-
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
|
23
|
-
|
10
|
+
#erd_box {
|
11
|
+
display: -webkit-box;
|
12
|
+
display: -moz-box;
|
13
|
+
display: box;
|
14
|
+
}
|
24
15
|
#erd_container {
|
25
|
-
|
16
|
+
-webkit-box-flex: 1;
|
17
|
+
-moz-box-flex: 1;
|
18
|
+
box-flex: 1;
|
19
|
+
}
|
20
|
+
@mixin table-header {
|
21
|
+
background: -webkit-gradient(linear, left top, left bottom, color-stop(0.88, #aaa), color-stop(0.00, #eee));
|
22
|
+
background: -webkit-linear-gradient(top, #eee 0%, #aaa 88%);
|
23
|
+
background: -moz-linear-gradient(top, #eee 0%, #aaa 88%);
|
24
|
+
background: -o-linear-gradient(top, #eee 0%, #aaa 88%);
|
25
|
+
background: -ms-linear-gradient(top, #eee 0%, #aaa 88%);
|
26
|
+
background: linear-gradient(to bottom, #eee 0%, #aaa 88%);
|
27
|
+
font-weight: normal;
|
26
28
|
}
|
27
29
|
|
28
30
|
#migration {
|
29
|
-
position: relative;
|
30
|
-
float: right;
|
31
|
-
z-index: 999;
|
32
31
|
|
33
32
|
table {
|
34
33
|
td {
|
35
34
|
font-size: small;
|
36
35
|
}
|
36
|
+
th {
|
37
|
+
@include table-header;
|
38
|
+
}
|
37
39
|
}
|
38
40
|
}
|
39
41
|
|
40
42
|
#erd {
|
41
|
-
position: absolute;
|
42
43
|
|
43
44
|
form {
|
44
45
|
* {
|
@@ -53,7 +54,23 @@ fieldset { padding:0; border:0; margin-top:25px; }
|
|
53
54
|
cursor: move;
|
54
55
|
|
55
56
|
a.close {
|
56
|
-
position:absolute;
|
57
|
+
position:absolute;
|
58
|
+
top:-6px;
|
59
|
+
right:-6px;
|
60
|
+
z-index:5;
|
61
|
+
vertical-align:middle;
|
62
|
+
line-height: 13px;
|
63
|
+
font-family:Arial, sans-serif;
|
64
|
+
text-decoration:none;
|
65
|
+
font-weight:normal;
|
66
|
+
background-color:#eee;
|
67
|
+
border:1px solid #500;
|
68
|
+
color:#500;
|
69
|
+
display:block;
|
70
|
+
width:16px;
|
71
|
+
height:16px;
|
72
|
+
text-align:center;
|
73
|
+
border-radius: 8px;
|
57
74
|
}
|
58
75
|
div.add_column_box {
|
59
76
|
text-align: center;
|
@@ -70,6 +87,7 @@ fieldset { padding:0; border:0; margin-top:25px; }
|
|
70
87
|
margin: 1px 5px 0 5px auto;
|
71
88
|
div.model_name_text {
|
72
89
|
text-align: center;
|
90
|
+
@include table-header;
|
73
91
|
}
|
74
92
|
}
|
75
93
|
div.model_name > div.model_name_text:hover {
|
@@ -132,3 +150,4 @@ table, th, td {
|
|
132
150
|
border: 1px #000 solid;
|
133
151
|
border-collapse: collapse;
|
134
152
|
}
|
153
|
+
|
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'rails/generators'
|
2
1
|
require 'nokogiri'
|
3
2
|
require 'rails_erd/diagram/graphviz'
|
4
3
|
require 'erd/application_controller'
|
5
4
|
|
6
5
|
module Erd
|
7
|
-
class MigrationError < StandardError; end
|
8
|
-
|
9
6
|
class ErdController < ::Erd::ApplicationController
|
10
7
|
def index
|
11
8
|
Rails.application.eager_load!
|
@@ -19,18 +16,7 @@ module Erd
|
|
19
16
|
end
|
20
17
|
@erd = render_plain plain, positions
|
21
18
|
|
22
|
-
|
23
|
-
@migrations = []
|
24
|
-
ActiveRecord::Migrator.migrations_paths.each do |path|
|
25
|
-
Dir.foreach(Rails.root.join(path)) do |file|
|
26
|
-
if (version_and_name = /^(\d{3,})_(.+)\.rb$/.match(file))
|
27
|
-
status = migrated_versions.delete(version_and_name[1]) ? 'up' : 'down'
|
28
|
-
@migrations << {status: status, version: version_and_name[1], name: version_and_name[2]}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
@migrations += migrated_versions.map {|v| {status: 'up', version: v, name: '*** NO FILE ***'}}
|
33
|
-
@migrations.sort_by! {|m| m[:version]}
|
19
|
+
@migrations = Erd::Migrator.status
|
34
20
|
end
|
35
21
|
|
36
22
|
def update
|
@@ -39,29 +25,23 @@ module Erd
|
|
39
25
|
changes.each do |row|
|
40
26
|
begin
|
41
27
|
action, model, column, from, to = row['action'], row['model'].tableize, row['column'], row['from'], row['to']
|
42
|
-
before_migration_files = Dir.glob Rails.root.join('db', 'migrate', '*.rb')
|
43
28
|
case action
|
44
29
|
when 'remove_model'
|
45
|
-
execute_generate_migration "drop_#{model}"
|
46
|
-
generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first
|
30
|
+
generated_migration_file = Erd::Migrator.execute_generate_migration "drop_#{model}"
|
47
31
|
gsub_file generated_migration_file, /def up.* end/m, "def change\n drop_table :#{model}\n end"
|
48
32
|
when 'rename_model'
|
49
33
|
from, to = from.tableize, to.tableize
|
50
|
-
execute_generate_migration "rename_#{from}_to_#{to}"
|
51
|
-
generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first
|
34
|
+
generated_migration_file = Erd::Migrator.execute_generate_migration "rename_#{from}_to_#{to}"
|
52
35
|
gsub_file generated_migration_file, /def up.* end/m, "def change\n rename_table :#{from}, :#{to}\n end"
|
53
36
|
when 'add_column'
|
54
37
|
name_and_type = column.scan(/(.*)\((.*?)\)/).first
|
55
38
|
name, type = name_and_type[0], name_and_type[1]
|
56
|
-
execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"]
|
57
|
-
generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first
|
39
|
+
Erd::Migrator.execute_generate_migration "add_#{name}_to_#{model}", ["#{name}:#{type}"]
|
58
40
|
when 'rename_column'
|
59
|
-
execute_generate_migration "rename_#{model}_#{from}_to_#{to}"
|
60
|
-
generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first
|
41
|
+
generated_migration_file = Erd::Migrator.execute_generate_migration "rename_#{model}_#{from}_to_#{to}"
|
61
42
|
gsub_file generated_migration_file, /def up.* end/m, "def change\n rename_column :#{model}, :#{from}, :#{to}\n end"
|
62
43
|
when 'alter_column'
|
63
|
-
execute_generate_migration "change_#{model}_#{column}_type_to_#{to}"
|
64
|
-
generated_migration_file = (Dir.glob(Rails.root.join('db', 'migrate', '*.rb')) - before_migration_files).first
|
44
|
+
generated_migration_file = Erd::Migrator.execute_generate_migration "change_#{model}_#{column}_type_to_#{to}"
|
65
45
|
gsub_file generated_migration_file, /def up.* end/m, "def change\n change_column :#{model}, :#{column}, :#{to}\n end"
|
66
46
|
when 'move'
|
67
47
|
json_file = Rails.root.join('tmp', 'erd_positions.json')
|
@@ -80,7 +60,7 @@ module Erd
|
|
80
60
|
end
|
81
61
|
|
82
62
|
def migrate
|
83
|
-
run_migrations :up => params[:up], :down => params[:down]
|
63
|
+
Erd::Migrator.run_migrations :up => params[:up], :down => params[:down]
|
84
64
|
redirect_to erd.root_path
|
85
65
|
end
|
86
66
|
|
@@ -91,51 +71,20 @@ module Erd
|
|
91
71
|
# node name x y width height label style shape color fillcolor
|
92
72
|
models = plain.scan(/^node ([^ ]+) ([0-9\.]+) ([0-9\.]+) ([0-9\.]+) ([0-9\.]+) <\{?(<((?!^\}?>).)*)^\}?> [^ ]+ [^ ]+ [^ ]+ [^ ]+\n/m).map {|node_name, x, y, width, height, label|
|
93
73
|
label_doc = Nokogiri::HTML::DocumentFragment.parse(label)
|
94
|
-
model_name =
|
74
|
+
model_name = node_name.sub(/^m_/, '')
|
95
75
|
next if model_name == 'ActiveRecord::SchemaMigration'
|
96
76
|
columns = []
|
97
77
|
if (cols_table = label_doc.search('table')[1])
|
98
78
|
columns = cols_table.search('tr > td').map {|col| col_name, col_type = col.text.split(' '); {:name => col_name, :type => col_type}}
|
99
79
|
end
|
100
80
|
custom_x, custom_y = positions[model_name.tableize].try(:split, ',')
|
101
|
-
{:model => model_name, :
|
81
|
+
{:model => model_name, :x => (custom_x || BigDecimal(x) * ratio), :y => (custom_y || BigDecimal(y) * ratio), :width => BigDecimal(width) * ratio, :height => height, :columns => columns}
|
102
82
|
}.compact
|
103
83
|
# edge tail head n x1 y1 .. xn yn [label xl yl] style color
|
104
|
-
edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from, :to => to}}
|
84
|
+
edges = plain.scan(/^edge ([^ ]+)+ ([^ ]+)/).map {|from, to| {:from => from.sub(/^m_/, ''), :to => to.sub(/^m_/, '')}}
|
105
85
|
render_to_string 'erd/erd/erd', :layout => nil, :locals => {:width => BigDecimal(svg_width) * ratio, :height => BigDecimal(svg_height) * ratio, :models => models, :edges => edges}
|
106
86
|
end
|
107
87
|
|
108
|
-
def execute_generate_migration(name, options = nil)
|
109
|
-
overwriting_argv([name, options]) do
|
110
|
-
Rails::Generators.configure! Rails.application.config.generators
|
111
|
-
result = Rails::Generators.invoke 'migration', [name, options], :behavior => :invoke, :destination_root => Rails.root
|
112
|
-
raise ::Erd::MigrationError, "#{name}#{"(#{options})" if options}" unless result
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# `rake db:migrate`
|
117
|
-
def run_migrations(migrations)
|
118
|
-
migrations.each do |direction, versions|
|
119
|
-
versions.each do |version|
|
120
|
-
ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_path, version.to_i)
|
121
|
-
end if versions
|
122
|
-
end
|
123
|
-
if ActiveRecord::Base.schema_format == :ruby
|
124
|
-
File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", 'w') do |file|
|
125
|
-
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# a dirty workaround to make rspec-rails run
|
131
|
-
def overwriting_argv(value, &block)
|
132
|
-
original_argv = ARGV
|
133
|
-
Object.const_set :ARGV, value
|
134
|
-
block.call
|
135
|
-
ensure
|
136
|
-
Object.const_set :ARGV, original_argv
|
137
|
-
end
|
138
|
-
|
139
88
|
def gsub_file(path, flag, *args, &block)
|
140
89
|
path = File.expand_path path, Rails.root
|
141
90
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div id="
|
1
|
+
<div id="erd-<%= model[:model] %>" class="model" style="top: <%= model[:y] %>px; left: <%= model[:x] %>px;" data-model_name="<%= model[:model] %>">
|
2
2
|
<a href="#!" class="close"> x </a>
|
3
3
|
<div class="model_name">
|
4
4
|
<div class="model_name_text"><%= model[:model] %></div>
|
@@ -1,6 +1,4 @@
|
|
1
|
-
<div id="erd"
|
1
|
+
<div id="erd" data-svg_width="<%= width %>" data-svg_height="<%= height %>">
|
2
2
|
<%= render :partial => 'erd/erd/model', :collection => models -%>
|
3
|
-
<svg width="<%= width %>pt" height="<%= height %>pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
4
|
-
</svg>
|
5
3
|
<script>window.raw_edges = <%= edges.to_json.html_safe %>;</script>
|
6
4
|
</div>
|
data/erd.gemspec
CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_runtime_dependency 'rails-erd', ['>= 0.4.5']
|
19
19
|
gem.add_runtime_dependency 'nokogiri'
|
20
20
|
|
21
|
-
gem.add_development_dependency 'ruby-debug19'
|
22
|
-
gem.add_development_dependency 'combustion', '~> 0.3.1'
|
23
21
|
gem.add_development_dependency 'rspec-rails'
|
22
|
+
gem.add_development_dependency 'capybara'
|
23
|
+
gem.add_development_dependency 'rr'
|
24
24
|
gem.add_development_dependency 'sqlite3'
|
25
25
|
end
|
data/lib/erd/migrator.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Erd
|
4
|
+
class MigrationError < StandardError; end
|
5
|
+
|
6
|
+
class Migrator
|
7
|
+
class << self
|
8
|
+
def status
|
9
|
+
migrated_versions = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}").map {|v| '%.3d' % v}
|
10
|
+
migrations = []
|
11
|
+
ActiveRecord::Migrator.migrations_paths.each do |path|
|
12
|
+
Dir.foreach(Rails.root.join(path)) do |file|
|
13
|
+
if (version_and_name = /^(\d{3,})_(.+)\.rb$/.match(file))
|
14
|
+
status = migrated_versions.delete(version_and_name[1]) ? 'up' : 'down'
|
15
|
+
migrations << {:status => status, :version => version_and_name[1], :name => version_and_name[2]}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
migrations += migrated_versions.map {|v| {:status => 'up', :version => v, :name => '*** NO FILE ***'}}
|
20
|
+
migrations.sort_by {|m| m[:version]}
|
21
|
+
end
|
22
|
+
|
23
|
+
# `rake db:migrate`
|
24
|
+
def run_migrations(migrations)
|
25
|
+
migrations.each do |direction, versions|
|
26
|
+
versions.each do |version|
|
27
|
+
ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_path, version.to_i)
|
28
|
+
end if versions
|
29
|
+
end
|
30
|
+
if ActiveRecord::Base.schema_format == :ruby
|
31
|
+
File.open(ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb", 'w') do |file|
|
32
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
#TODO unload migraion classes
|
36
|
+
end
|
37
|
+
|
38
|
+
# runs `rails g migration [name]`
|
39
|
+
# @return generated migration filename
|
40
|
+
def execute_generate_migration(name, options = nil)
|
41
|
+
overwriting_argv([name, options]) do
|
42
|
+
Rails::Generators.configure! Rails.application.config.generators
|
43
|
+
result = Rails::Generators.invoke 'migration', [name, options], :behavior => :invoke, :destination_root => Rails.root
|
44
|
+
raise ::Erd::MigrationError, "#{name}#{"(#{options})" if options}" unless result
|
45
|
+
result.last.last
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
# a dirty workaround to make rspec-rails run
|
51
|
+
def overwriting_argv(value, &block)
|
52
|
+
original_argv = ARGV
|
53
|
+
Object.const_set :ARGV, value
|
54
|
+
block.call
|
55
|
+
ensure
|
56
|
+
Object.const_set :ARGV, original_argv
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/erd/railtie.rb
CHANGED
data/lib/erd/version.rb
CHANGED
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'action_controller/railtie'
|
3
|
+
|
4
|
+
# config
|
5
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
6
|
+
|
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
|
+
|
16
|
+
config.app_generators.orm :active_record, :migration => true, :timestamps => true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
ErdApp::Application.initialize!
|
20
|
+
|
21
|
+
# models
|
22
|
+
class Author < ActiveRecord::Base
|
23
|
+
has_many :books
|
24
|
+
end
|
25
|
+
class Book < ActiveRecord::Base
|
26
|
+
belongs_to :author
|
27
|
+
end
|
28
|
+
|
29
|
+
# helpers
|
30
|
+
module ApplicationHelper; end
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Erd::Migrator do
|
4
|
+
subject { Erd::Migrator }
|
5
|
+
after do
|
6
|
+
Dir.glob(Rails.root.join('db/migrate/*.rb')).each do |f|
|
7
|
+
FileUtils.rm f unless File.basename(f).in? %w(20120428022519_create_authors.rb 20120428022535_create_books.rb)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
describe '.status' do
|
11
|
+
context 'when all migrations are up' do
|
12
|
+
its(:status) { should == [{:status => 'up', :version => '20120428022519', :name => 'create_authors'}, {:status => 'up', :version => '20120428022535', :name => 'create_books'}] }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when one is undone' do
|
16
|
+
before do
|
17
|
+
FileUtils.touch Rails.root.join('db/migrate/20999999999999_create_foobars.rb')
|
18
|
+
end
|
19
|
+
its(:status) { should == [{:status => 'up', :version => '20120428022519', :name => 'create_authors'}, {:status => 'up', :version => '20120428022535', :name => 'create_books'}, {:status => 'down', :version => '20999999999999', :name => 'create_foobars'}] }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '.run_migrations' do
|
24
|
+
before do
|
25
|
+
FileUtils.touch Rails.root.join('db/migrate/20999999999999_create_foobars.rb')
|
26
|
+
mock(ActiveRecord::Migrator).run(:up, 'db/migrate', 20999999999999)
|
27
|
+
mock(ActiveRecord::SchemaDumper).dump(ActiveRecord::Base.connection, anything)
|
28
|
+
end
|
29
|
+
specify do
|
30
|
+
subject.run_migrations(:up => ['20999999999999'])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.execute_generate_migration' do
|
35
|
+
before do
|
36
|
+
stub.proxy(Time).now {|t| stub(t).utc { Time.new 2012, 5, 12, 13, 26 } }
|
37
|
+
end
|
38
|
+
specify do
|
39
|
+
subject.execute_generate_migration('create_foobars').should eq Rails.root.join('db/migrate', '20120512132600_create_foobars.rb').to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
feature 'erd#index' do
|
4
|
+
scenario 'with author and book model' do
|
5
|
+
visit '/erd'
|
6
|
+
page.should have_content 'Author'
|
7
|
+
page.should have_content 'name'
|
8
|
+
page.should have_content 'Book'
|
9
|
+
page.should have_content 'title'
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
# load Rails first
|
4
|
+
require 'rails'
|
5
|
+
require 'erd'
|
6
|
+
# needs to load the app before loading rspec/rails => capybara
|
7
|
+
require 'fake_app/fake_app'
|
8
8
|
require 'rspec/rails'
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
12
|
|
10
13
|
RSpec.configure do |config|
|
11
|
-
config.
|
14
|
+
config.mock_with :rr
|
15
|
+
config.before :all do
|
16
|
+
ActiveRecord::Migration.verbose = false
|
17
|
+
ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths.map {|p| Rails.root.join p}, nil)
|
18
|
+
end
|
12
19
|
end
|
metadata
CHANGED
@@ -1,89 +1,118 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: erd
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Akira Matsuda
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-05-22 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: rails-erd
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 5
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 4
|
32
|
+
- 5
|
21
33
|
version: 0.4.5
|
22
34
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
26
37
|
name: nokogiri
|
27
|
-
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
40
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
33
48
|
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rspec-rails
|
34
52
|
prerelease: false
|
35
|
-
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: ruby-debug19
|
38
|
-
requirement: &70212334460620 !ruby/object:Gem::Requirement
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
54
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
44
62
|
type: :development
|
63
|
+
version_requirements: *id003
|
64
|
+
- !ruby/object:Gem::Dependency
|
65
|
+
name: capybara
|
45
66
|
prerelease: false
|
46
|
-
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: combustion
|
49
|
-
requirement: &70212334459800 !ruby/object:Gem::Requirement
|
67
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
68
|
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
55
76
|
type: :development
|
77
|
+
version_requirements: *id004
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rr
|
56
80
|
prerelease: false
|
57
|
-
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: rspec-rails
|
60
|
-
requirement: &70212334459100 !ruby/object:Gem::Requirement
|
81
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
61
82
|
none: false
|
62
|
-
requirements:
|
63
|
-
- -
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
66
90
|
type: :development
|
67
|
-
|
68
|
-
|
69
|
-
- !ruby/object:Gem::Dependency
|
91
|
+
version_requirements: *id005
|
92
|
+
- !ruby/object:Gem::Dependency
|
70
93
|
name: sqlite3
|
71
|
-
|
94
|
+
prerelease: false
|
95
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
72
96
|
none: false
|
73
|
-
requirements:
|
74
|
-
- -
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
77
104
|
type: :development
|
78
|
-
|
79
|
-
version_requirements: *70212334458260
|
105
|
+
version_requirements: *id006
|
80
106
|
description: erd engine on Rails
|
81
|
-
email:
|
107
|
+
email:
|
82
108
|
- ronnie@dio.jp
|
83
109
|
executables: []
|
110
|
+
|
84
111
|
extensions: []
|
112
|
+
|
85
113
|
extra_rdoc_files: []
|
86
|
-
|
114
|
+
|
115
|
+
files:
|
87
116
|
- .gitignore
|
88
117
|
- Gemfile
|
89
118
|
- MIT-LICENSE
|
@@ -105,51 +134,59 @@ files:
|
|
105
134
|
- erd.gemspec
|
106
135
|
- lib/erd.rb
|
107
136
|
- lib/erd/engine.rb
|
137
|
+
- lib/erd/migrator.rb
|
108
138
|
- lib/erd/railtie.rb
|
109
139
|
- lib/erd/version.rb
|
110
|
-
- spec/
|
111
|
-
- spec/
|
112
|
-
- spec/
|
113
|
-
- spec/
|
114
|
-
- spec/
|
115
|
-
- spec/
|
116
|
-
- spec/
|
117
|
-
- spec/
|
118
|
-
- spec/internal/public/favicon.ico
|
140
|
+
- spec/fake_app/db/migrate/20120428022519_create_authors.rb
|
141
|
+
- spec/fake_app/db/migrate/20120428022535_create_books.rb
|
142
|
+
- spec/fake_app/db/schema.rb
|
143
|
+
- spec/fake_app/fake_app.rb
|
144
|
+
- spec/fake_app/log/.gitignore
|
145
|
+
- spec/fake_app/tmp/.gitkeep
|
146
|
+
- spec/lib/migrator_spec.rb
|
147
|
+
- spec/requests/erd_spec.rb
|
119
148
|
- spec/spec_helper.rb
|
120
149
|
- vendor/assets/javascripts/raphael-min.js
|
121
150
|
homepage: https://github.com/amatsuda/erd
|
122
151
|
licenses: []
|
152
|
+
|
123
153
|
post_install_message:
|
124
154
|
rdoc_options: []
|
125
|
-
|
155
|
+
|
156
|
+
require_paths:
|
126
157
|
- lib
|
127
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
159
|
none: false
|
129
|
-
requirements:
|
130
|
-
- -
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
|
133
|
-
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
hash: 3
|
164
|
+
segments:
|
165
|
+
- 0
|
166
|
+
version: "0"
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
168
|
none: false
|
135
|
-
requirements:
|
136
|
-
- -
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
hash: 3
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
version: "0"
|
139
176
|
requirements: []
|
177
|
+
|
140
178
|
rubyforge_project:
|
141
|
-
rubygems_version: 1.8.
|
179
|
+
rubygems_version: 1.8.10
|
142
180
|
signing_key:
|
143
181
|
specification_version: 3
|
144
182
|
summary: erd engine on Rails
|
145
|
-
test_files:
|
146
|
-
- spec/
|
147
|
-
- spec/
|
148
|
-
- spec/
|
149
|
-
- spec/
|
150
|
-
- spec/
|
151
|
-
- spec/
|
152
|
-
- spec/
|
153
|
-
- spec/
|
154
|
-
- spec/internal/public/favicon.ico
|
183
|
+
test_files:
|
184
|
+
- spec/fake_app/db/migrate/20120428022519_create_authors.rb
|
185
|
+
- spec/fake_app/db/migrate/20120428022535_create_books.rb
|
186
|
+
- spec/fake_app/db/schema.rb
|
187
|
+
- spec/fake_app/fake_app.rb
|
188
|
+
- spec/fake_app/log/.gitignore
|
189
|
+
- spec/fake_app/tmp/.gitkeep
|
190
|
+
- spec/lib/migrator_spec.rb
|
191
|
+
- spec/requests/erd_spec.rb
|
155
192
|
- spec/spec_helper.rb
|
Binary file
|
data/spec/internal/db/schema.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
ActiveRecord::Schema.define do
|
2
|
-
create_table "posts", :force => true do |t|
|
3
|
-
t.string "title"
|
4
|
-
t.text "content"
|
5
|
-
t.integer "user_id"
|
6
|
-
t.datetime "created_at", :null => false
|
7
|
-
t.datetime "updated_at", :null => false
|
8
|
-
end
|
9
|
-
|
10
|
-
create_table "users", :force => true do |t|
|
11
|
-
t.string "name"
|
12
|
-
t.datetime "created_at", :null => false
|
13
|
-
t.datetime "updated_at", :null => false
|
14
|
-
end
|
15
|
-
end
|