schema_plus 1.8.9 → 2.0.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +4 -4
- data/.travis.yml +1 -47
- data/CHANGELOG.md +0 -35
- data/README.md +73 -107
- data/Rakefile +7 -10
- data/TODO.md +51 -0
- data/gemfiles/Gemfile.base +2 -0
- data/lib/schema_column_plus.rb +7 -0
- data/lib/{schema_plus → schema_column_plus}/active_record/connection_adapters/column.rb +13 -11
- data/lib/schema_column_plus/middleware/model.rb +22 -0
- data/lib/schema_db_default.rb +13 -0
- data/lib/{schema_plus → schema_db_default}/active_record/attribute.rb +4 -4
- data/lib/schema_db_default/db_default.rb +17 -0
- data/lib/schema_db_default/middleware.rb +30 -0
- data/lib/schema_default_expr.rb +32 -0
- data/lib/schema_default_expr/active_record/connection_adapters/mysql_adapter.rb +17 -0
- data/lib/schema_default_expr/active_record/connection_adapters/postgresql_adapter.rb +18 -0
- data/lib/schema_default_expr/active_record/connection_adapters/sqlite3_adapter.rb +35 -0
- data/lib/schema_default_expr/middleware.rb +54 -0
- data/lib/schema_pg_enums.rb +6 -0
- data/lib/schema_pg_enums/active_record.rb +69 -0
- data/lib/schema_pg_enums/middleware.rb +23 -0
- data/lib/schema_plus.rb +17 -45
- data/lib/schema_plus/active_record/base.rb +6 -23
- data/lib/schema_plus/active_record/connection_adapters/abstract_adapter.rb +80 -181
- data/lib/schema_plus/active_record/connection_adapters/foreign_key_definition.rb +78 -99
- data/lib/schema_plus/active_record/connection_adapters/mysql_adapter.rb +34 -114
- data/lib/schema_plus/active_record/connection_adapters/postgresql_adapter.rb +16 -370
- data/lib/schema_plus/active_record/connection_adapters/schema_statements.rb +1 -67
- data/lib/schema_plus/active_record/connection_adapters/sqlite3_adapter.rb +18 -112
- data/lib/schema_plus/active_record/connection_adapters/table_definition.rb +14 -116
- data/lib/schema_plus/active_record/migration/command_recorder.rb +8 -59
- data/lib/schema_plus/middleware/dumper.rb +94 -0
- data/lib/schema_plus/middleware/migration.rb +167 -0
- data/lib/schema_plus/middleware/model.rb +17 -0
- data/lib/schema_plus/version.rb +1 -1
- data/lib/schema_plus_tables.rb +15 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/abstract_adapter.rb +20 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/mysql_adapter.rb +25 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/postgresql_adapter.rb +13 -0
- data/lib/schema_plus_tables/active_record/connection_adapters/sqlite3_adapter.rb +12 -0
- data/lib/schema_views.rb +16 -0
- data/lib/schema_views/active_record/connection_adapters/abstract_adapter.rb +41 -0
- data/lib/schema_views/active_record/connection_adapters/mysql_adapter.rb +30 -0
- data/lib/schema_views/active_record/connection_adapters/postgresql_adapter.rb +31 -0
- data/lib/schema_views/active_record/connection_adapters/sqlite3_adapter.rb +18 -0
- data/lib/schema_views/middleware.rb +47 -0
- data/schema_dev.yml +1 -31
- data/schema_plus.gemspec +11 -9
- data/spec/foreign_key_definition_spec.rb +7 -7
- data/spec/foreign_key_spec.rb +63 -48
- data/spec/migration_spec.rb +58 -203
- data/spec/named_schemas_spec.rb +5 -88
- data/spec/{column_spec.rb → schema_column_plus/column_spec.rb} +26 -48
- data/spec/schema_db_default/column_spec.rb +58 -0
- data/spec/{column_default_spec.rb → schema_default_expr/column_default_spec.rb} +1 -2
- data/spec/schema_default_expr/schema_dumper_spec.rb +116 -0
- data/spec/schema_dumper_spec.rb +22 -327
- data/spec/{enum_spec.rb → schema_pg_enums/enum_spec.rb} +1 -1
- data/spec/schema_pg_enums/schema_dumper_spec.rb +37 -0
- data/spec/schema_views/named_schemas_spec.rb +97 -0
- data/spec/{views_spec.rb → schema_views/views_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/support/matchers/reference.rb +11 -12
- metadata +104 -57
- data/gemfiles/rails-3.2/Gemfile.base +0 -3
- data/gemfiles/rails-3.2/Gemfile.mysql +0 -10
- data/gemfiles/rails-3.2/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-3.2/Gemfile.postgresql +0 -10
- data/gemfiles/rails-3.2/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.0/Gemfile.base +0 -3
- data/gemfiles/rails-4.0/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.0/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.0/Gemfile.sqlite3 +0 -10
- data/gemfiles/rails-4.1/Gemfile.base +0 -3
- data/gemfiles/rails-4.1/Gemfile.mysql2 +0 -10
- data/gemfiles/rails-4.1/Gemfile.postgresql +0 -10
- data/gemfiles/rails-4.1/Gemfile.sqlite3 +0 -10
- data/lib/schema_plus/active_record/column_options_handler.rb +0 -117
- data/lib/schema_plus/active_record/connection_adapters/index_definition.rb +0 -70
- data/lib/schema_plus/active_record/db_default.rb +0 -19
- data/lib/schema_plus/active_record/foreign_keys.rb +0 -137
- data/lib/schema_plus/active_record/schema_dumper.rb +0 -171
- data/lib/schema_plus/railtie.rb +0 -20
- data/spec/index_definition_spec.rb +0 -211
- data/spec/index_spec.rb +0 -249
data/spec/named_schemas_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "with multiple schemas" do
|
4
4
|
def connection
|
@@ -35,52 +35,6 @@ describe "with multiple schemas" do
|
|
35
35
|
end + ", login varchar(255))"
|
36
36
|
end
|
37
37
|
|
38
|
-
context "with indexes in each schema" do
|
39
|
-
before(:each) do
|
40
|
-
connection.execute 'CREATE INDEX ' + case connection.adapter_name
|
41
|
-
when /^mysql/i then "index_users_on_login ON schema_plus_test2.users"
|
42
|
-
when /^postgresql/i then "index_users_on_login ON schema_plus_test2.users"
|
43
|
-
when /^sqlite/i then "schema_plus_test2.index_users_on_login ON users"
|
44
|
-
end + " (login)"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should not find indexes in other schema" do
|
48
|
-
User.reset_column_information
|
49
|
-
expect(User.indexes).to be_empty
|
50
|
-
end
|
51
|
-
|
52
|
-
it "should find index in current schema" do
|
53
|
-
connection.execute 'CREATE INDEX index_users_on_login ON users (login)'
|
54
|
-
User.reset_column_information
|
55
|
-
expect(User.indexes.map(&:name)).to eq(['index_users_on_login'])
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context "with views in each schema" do
|
60
|
-
around(:each) do |example|
|
61
|
-
begin
|
62
|
-
example.run
|
63
|
-
ensure
|
64
|
-
connection.execute 'DROP VIEW schema_plus_test2.myview' rescue nil
|
65
|
-
connection.execute 'DROP VIEW myview' rescue nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
before(:each) do
|
70
|
-
connection.views.each { |view| connection.drop_view view }
|
71
|
-
connection.execute 'CREATE VIEW schema_plus_test2.myview AS SELECT * FROM users'
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should not find views in other schema" do
|
75
|
-
expect(connection.views).to be_empty
|
76
|
-
end
|
77
|
-
|
78
|
-
it "should find views in this schema" do
|
79
|
-
connection.execute 'CREATE VIEW myview AS SELECT * FROM users'
|
80
|
-
expect(connection.views).to eq(['myview'])
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
38
|
context "with foreign key in each schema" do
|
85
39
|
before(:each) do
|
86
40
|
class Comment < ::ActiveRecord::Base ; end
|
@@ -116,9 +70,9 @@ describe "with multiple schemas" do
|
|
116
70
|
t.integer :user_id, :foreign_key => true
|
117
71
|
end
|
118
72
|
Comment.reset_column_information
|
119
|
-
expect(Comment.foreign_keys.map(&:
|
73
|
+
expect(Comment.foreign_keys.map(&:column).flatten).to eq(["user_id"])
|
120
74
|
User.reset_column_information
|
121
|
-
expect(User.reverse_foreign_keys.map(&:
|
75
|
+
expect(User.reverse_foreign_keys.map(&:column).flatten).to eq(["user_id"])
|
122
76
|
end
|
123
77
|
|
124
78
|
end
|
@@ -165,11 +119,11 @@ describe "with multiple schemas" do
|
|
165
119
|
end
|
166
120
|
|
167
121
|
it "should reference table in same schema" do
|
168
|
-
expect(Member.foreign_keys.map(&:
|
122
|
+
expect(Member.foreign_keys.map(&:to_table)).to include "schema_plus_test2.groups"
|
169
123
|
end
|
170
124
|
|
171
125
|
it "should reference table in default schema", :mysql => :skip do
|
172
|
-
expect(Member.foreign_keys.map(&:
|
126
|
+
expect(Member.foreign_keys.map(&:to_table)).to include "items"
|
173
127
|
end
|
174
128
|
|
175
129
|
it "should include the schema in the constraint name" do
|
@@ -179,41 +133,4 @@ describe "with multiple schemas" do
|
|
179
133
|
end
|
180
134
|
end
|
181
135
|
|
182
|
-
context "when using PostGIS", :postgresql => :only do
|
183
|
-
before(:all) do
|
184
|
-
begin
|
185
|
-
connection.execute "CREATE SCHEMA postgis"
|
186
|
-
rescue ActiveRecord::StatementInvalid => e
|
187
|
-
raise unless e.message =~ /already exists/
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
around(:each) do |example|
|
192
|
-
begin
|
193
|
-
connection.execute "SET search_path to '$user','public','postgis'"
|
194
|
-
example.run
|
195
|
-
ensure
|
196
|
-
connection.execute "SET search_path to '$user','public'"
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
before(:each) do
|
201
|
-
allow(connection).to receive(:adapter_name).and_return('PostGIS')
|
202
|
-
end
|
203
|
-
|
204
|
-
it "should hide views in postgis schema" do
|
205
|
-
begin
|
206
|
-
connection.create_view "postgis.hidden", "select 1", :force => true
|
207
|
-
connection.create_view :myview, "select 2", :force => true
|
208
|
-
expect(connection.views).to eq(["myview"])
|
209
|
-
ensure
|
210
|
-
connection.execute 'DROP VIEW postgis.hidden' rescue nil
|
211
|
-
connection.execute 'DROP VIEW myview' rescue nil
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
136
|
end
|
217
|
-
|
218
|
-
|
219
|
-
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Column" do
|
4
4
|
|
@@ -15,8 +15,6 @@ describe "Column" do
|
|
15
15
|
end
|
16
16
|
it "works properly" do
|
17
17
|
type = case
|
18
|
-
when "#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}".to_r <= "4.1".to_r
|
19
|
-
{ "type" => "string" }
|
20
18
|
when SchemaDev::Rspec::Helpers.mysql?
|
21
19
|
{ "sql_type" => "varchar(255)" }
|
22
20
|
when SchemaDev::Rspec::Helpers.postgresql?
|
@@ -84,6 +82,31 @@ describe "Column" do
|
|
84
82
|
end
|
85
83
|
end
|
86
84
|
|
85
|
+
context "with case insensitive" do
|
86
|
+
before(:each) do
|
87
|
+
create_table(User, :login => { :index => {}})
|
88
|
+
User.reset_column_information
|
89
|
+
@column = User.columns.find(&its.name == "login")
|
90
|
+
end
|
91
|
+
|
92
|
+
context "index", :mysql => :skip do
|
93
|
+
|
94
|
+
it "reports column as case insensitive" do
|
95
|
+
allow(User.indexes.first).to receive(:case_sensitive?).and_return(false);
|
96
|
+
expect(@column).not_to be_case_sensitive
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "database", :mysql => :only do
|
101
|
+
|
102
|
+
# make sure we haven't broken mysql's method
|
103
|
+
it "reports column as case insensitive" do
|
104
|
+
allow(migration).to receive(:collation).and_return("utf8_unicode_ci") # mysql determines case insensitivity its own way
|
105
|
+
expect(@column).not_to be_case_sensitive
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
87
110
|
end
|
88
111
|
|
89
112
|
context "regarding when it requires a value" do
|
@@ -105,51 +128,6 @@ describe "Column" do
|
|
105
128
|
|
106
129
|
end
|
107
130
|
|
108
|
-
context "using DB_DEFAULT" do
|
109
|
-
|
110
|
-
before(:each) do
|
111
|
-
create_table(User, :alpha => { :default => "gabba" }, :beta => {})
|
112
|
-
end
|
113
|
-
|
114
|
-
it "creating a record should respect default expression", :sqlite3 => :skip do
|
115
|
-
User.create!(:alpha => ActiveRecord::DB_DEFAULT, :beta => "hello")
|
116
|
-
expect(User.last.alpha).to eq("gabba")
|
117
|
-
expect(User.last.beta).to eq("hello")
|
118
|
-
end
|
119
|
-
|
120
|
-
it "creating a record should raise an error", :sqlite3 => :only do
|
121
|
-
expect { User.create!(:alpha => ActiveRecord::DB_DEFAULT, :beta => "hello") }.to raise_error ActiveRecord::StatementInvalid
|
122
|
-
end
|
123
|
-
|
124
|
-
it "updating a record should respect default expression", :sqlite3 => :skip do
|
125
|
-
u = User.create!(:alpha => "hey", :beta => "hello")
|
126
|
-
u.reload
|
127
|
-
expect(u.alpha).to eq("hey")
|
128
|
-
expect(u.beta).to eq("hello")
|
129
|
-
u.update_attributes(:alpha => ActiveRecord::DB_DEFAULT, :beta => "goodbye")
|
130
|
-
u.reload
|
131
|
-
expect(u.alpha).to eq("gabba")
|
132
|
-
expect(u.beta).to eq("goodbye")
|
133
|
-
end
|
134
|
-
|
135
|
-
it "updating a record should raise an error", :sqlite3 => :only do
|
136
|
-
u = User.create!(:alpha => "hey", :beta => "hello")
|
137
|
-
expect { u.update_attributes(:alpha => ActiveRecord::DB_DEFAULT, :beta => "goodbye") }.to raise_error ActiveRecord::StatementInvalid
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
context "Postgresql array", :postgresql => :only do
|
142
|
-
|
143
|
-
before(:each) do
|
144
|
-
create_table(User, :alpha => { :default => [], :array => true })
|
145
|
-
end
|
146
|
-
|
147
|
-
it "respects array: true" do
|
148
|
-
column = User.columns.find(&its.name == "alpha")
|
149
|
-
expect(column.array).to be_truthy
|
150
|
-
end
|
151
|
-
end if "#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}".to_r >= "4.0".to_r
|
152
|
-
|
153
131
|
protected
|
154
132
|
|
155
133
|
def create_table(model, columns_with_options)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SchemaDbDefault do
|
4
|
+
|
5
|
+
let(:migration) { ::ActiveRecord::Migration }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
class User < ::ActiveRecord::Base ; end
|
9
|
+
create_table(User, :alpha => { :default => "gabba" }, :beta => {})
|
10
|
+
end
|
11
|
+
|
12
|
+
context "uses db default value", :sqlite3 => :skip do
|
13
|
+
|
14
|
+
it "when creating a record with DB_DEFAULT" do
|
15
|
+
User.create!(:alpha => ActiveRecord::DB_DEFAULT, :beta => "hello")
|
16
|
+
expect(User.last.alpha).to eq("gabba")
|
17
|
+
expect(User.last.beta).to eq("hello")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "when updating a record with DB_DEFAULT" do
|
21
|
+
u = User.create!(:alpha => "hey", :beta => "hello")
|
22
|
+
u.reload
|
23
|
+
expect(u.alpha).to eq("hey")
|
24
|
+
expect(u.beta).to eq("hello")
|
25
|
+
u.update_attributes(:alpha => ActiveRecord::DB_DEFAULT, :beta => "goodbye")
|
26
|
+
u.reload
|
27
|
+
expect(u.alpha).to eq("gabba")
|
28
|
+
expect(u.beta).to eq("goodbye")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "raises an error", :sqlite3 => :only do
|
34
|
+
|
35
|
+
it "when creating a record with DB_DEFAULT" do
|
36
|
+
expect { User.create!(:alpha => ActiveRecord::DB_DEFAULT, :beta => "hello") }.to raise_error ActiveRecord::StatementInvalid
|
37
|
+
end
|
38
|
+
|
39
|
+
it "when updating a record with DB_DEFAULT" do
|
40
|
+
u = User.create!(:alpha => "hey", :beta => "hello")
|
41
|
+
expect { u.update_attributes(:alpha => ActiveRecord::DB_DEFAULT, :beta => "goodbye") }.to raise_error ActiveRecord::StatementInvalid
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def create_table(model, columns_with_options)
|
48
|
+
migration.suppress_messages do
|
49
|
+
migration.create_table model.table_name, :force => true do |t|
|
50
|
+
columns_with_options.each_pair do |column, options|
|
51
|
+
t.send :string, column, options
|
52
|
+
end
|
53
|
+
end
|
54
|
+
model.reset_column_information
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe "Schema dump" do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
SchemaPlus.setup do |config|
|
8
|
+
config.foreign_keys.auto_create = false
|
9
|
+
end
|
10
|
+
ActiveRecord::Migration.suppress_messages do
|
11
|
+
ActiveRecord::Schema.define do
|
12
|
+
connection.tables.each do |table| drop_table table, :cascade => true end
|
13
|
+
|
14
|
+
create_table :posts, :force => true do |t|
|
15
|
+
t.text :body
|
16
|
+
t.integer :user_id
|
17
|
+
t.integer :first_comment_id
|
18
|
+
t.string :string_no_default
|
19
|
+
t.integer :short_id
|
20
|
+
t.string :str_short
|
21
|
+
t.integer :integer_col
|
22
|
+
t.float :float_col
|
23
|
+
t.decimal :decimal_col
|
24
|
+
t.datetime :datetime_col
|
25
|
+
t.timestamp :timestamp_col
|
26
|
+
t.time :time_col
|
27
|
+
t.date :date_col
|
28
|
+
t.binary :binary_col
|
29
|
+
t.boolean :boolean_col
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class ::Post < ActiveRecord::Base ; end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with date default", :postgresql => :only do
|
38
|
+
it "should dump the default hash expr as now()" do
|
39
|
+
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
40
|
+
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr\s*=>)\s*"now\(\)"\s*\}})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should dump the default hash expr as CURRENT_TIMESTAMP" do
|
45
|
+
with_additional_column Post, :posted_at, :datetime, :default => {:expr => 'date \'2001-09-28\''} do
|
46
|
+
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>).*2001-09-28.*})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "can dump a complex default expression" do
|
51
|
+
with_additional_column Post, :name, :string, :default => {:expr => 'substring(random()::text from 3 for 6)'} do
|
52
|
+
expect(dump_posts).to match(%r{t\.string\s+"name",\s*(?:default:|:default\s*=>)\s*{\s*(?:expr:|:expr\s*=>)\s*"\\"substring\\"\(\(random\(\)\)::text, 3, 6\)"\s*}})
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with date default", :sqlite3 => :only do
|
58
|
+
it "should dump the default hash expr as now" do
|
59
|
+
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
60
|
+
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should dump the default hash expr string as now" do
|
65
|
+
with_additional_column Post, :posted_at, :datetime, :default => { :expr => "(DATETIME('now'))" } do
|
66
|
+
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should dump the default value normally" do
|
71
|
+
with_additional_column Post, :posted_at, :string, :default => "now" do
|
72
|
+
expect(dump_posts).to match(%r{t\.string\s*"posted_at",\s*(?:default:|:default =>)\s*"now"})
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should leave out :default when default was changed to null" do
|
78
|
+
ActiveRecord::Migration.suppress_messages do
|
79
|
+
ActiveRecord::Migration.change_column_default :posts, :string_no_default, nil
|
80
|
+
end
|
81
|
+
# mysql2 includes 'limit: 255' in the output. that's OK, just want to
|
82
|
+
# make sure the full line doesn't have 'default' in it.
|
83
|
+
expect(dump_posts).to match(%r{t\.string\s+"string_no_default"\s*(,\s*limit:\s*\d+)?$})
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
def to_regexp(string)
|
88
|
+
Regexp.new(Regexp.escape(string))
|
89
|
+
end
|
90
|
+
|
91
|
+
def with_additional_column(model, column_name, column_type, options)
|
92
|
+
table_columns = model.columns.reject{|column| column.name == 'id'}
|
93
|
+
ActiveRecord::Migration.suppress_messages do
|
94
|
+
ActiveRecord::Migration.create_table model.table_name, :force => true do |t|
|
95
|
+
table_columns.each do |column|
|
96
|
+
t.column column.name, column.type, :default => column.default
|
97
|
+
end
|
98
|
+
t.column column_name, column_type, options
|
99
|
+
end
|
100
|
+
end
|
101
|
+
yield
|
102
|
+
end
|
103
|
+
|
104
|
+
def dump_schema(opts={})
|
105
|
+
stream = StringIO.new
|
106
|
+
ActiveRecord::SchemaDumper.ignore_tables = Array.wrap(opts[:ignore]) || []
|
107
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
108
|
+
stream.string
|
109
|
+
end
|
110
|
+
|
111
|
+
def dump_posts
|
112
|
+
dump_schema(:ignore => %w[users comments])
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
data/spec/schema_dumper_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'stringio'
|
3
3
|
|
4
4
|
describe "Schema dump" do
|
@@ -49,13 +49,13 @@ describe "Schema dump" do
|
|
49
49
|
|
50
50
|
it "should include foreign_key definition" do
|
51
51
|
with_foreign_key Post, :user_id, :users, :id do
|
52
|
-
expect(dump_posts).to match(
|
52
|
+
expect(dump_posts).to match(%r{t.integer\s+"user_id".*foreign_key.*users})
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should include foreign_key name" do
|
57
57
|
with_foreign_key Post, :user_id, :users, :id, :name => "yippee" do
|
58
|
-
expect(dump_posts).to match(/foreign_key.*
|
58
|
+
expect(dump_posts).to match(/user_id.*foreign_key.*users.*name: "yippee"/)
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -66,7 +66,7 @@ describe "Schema dump" do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
|
69
|
-
|
69
|
+
xit "should sort foreign_key definitions" do
|
70
70
|
with_foreign_keys Comment, [ [ :post_id, :posts, :id ], [ :commenter_id, :users, :id ]] do
|
71
71
|
expect(dump_schema).to match(/foreign_key.+commenter_id.+foreign_key.+post_id/m)
|
72
72
|
end
|
@@ -94,183 +94,19 @@ describe "Schema dump" do
|
|
94
94
|
|
95
95
|
end
|
96
96
|
|
97
|
-
context "with date default", :postgresql => :only do
|
98
|
-
it "should dump the default hash expr as now()" do
|
99
|
-
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
100
|
-
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr\s*=>)\s*"now\(\)"\s*\}})
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should dump the default hash expr as CURRENT_TIMESTAMP" do
|
105
|
-
with_additional_column Post, :posted_at, :datetime, :default => {:expr => 'date \'2001-09-28\''} do
|
106
|
-
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>).*2001-09-28.*})
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
it "can dump a complex default expression" do
|
111
|
-
with_additional_column Post, :name, :string, :default => {:expr => 'substring(random()::text from 3 for 6)'} do
|
112
|
-
expect(dump_posts).to match(%r{t\.string\s+"name",\s*(?:default:|:default\s*=>)\s*{\s*(?:expr:|:expr\s*=>)\s*"\\"substring\\"\(\(random\(\)\)::text, 3, 6\)"\s*}})
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context "with date default", :sqlite3 => :only do
|
118
|
-
it "should dump the default hash expr as now" do
|
119
|
-
with_additional_column Post, :posted_at, :datetime, :default => :now do
|
120
|
-
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should dump the default hash expr string as now" do
|
125
|
-
with_additional_column Post, :posted_at, :datetime, :default => { :expr => "(DATETIME('now'))" } do
|
126
|
-
expect(dump_posts).to match(%r{t\.datetime\s+"posted_at",\s*(?:default:|:default =>)\s*\{\s*(?:expr:|:expr =>)\s*"\(DATETIME\('now'\)\)"\s*\}})
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should dump the default value normally" do
|
131
|
-
with_additional_column Post, :posted_at, :string, :default => "now" do
|
132
|
-
expect(dump_posts).to match(%r{t\.string\s*"posted_at",\s*(?:default:|:default =>)\s*"now"})
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should leave out :default when default was changed to null" do
|
138
|
-
ActiveRecord::Migration.suppress_messages do
|
139
|
-
ActiveRecord::Migration.change_column_default :posts, :string_no_default, nil
|
140
|
-
end
|
141
|
-
# mysql2 includes 'limit: 255' in the output. that's OK, just want to
|
142
|
-
# make sure the full line doesn't have 'default' in it.
|
143
|
-
expect(dump_posts).to match(%r{t\.string\s+"string_no_default"\s*(,\s*limit:\s*\d+)?$})
|
144
|
-
end
|
145
|
-
|
146
97
|
it "should include foreign_key options" do
|
147
|
-
with_foreign_key Post, :user_id, :users, :id, :on_update => :cascade, :on_delete => :
|
148
|
-
expect(dump_posts).to match(
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
it "should include index definition" do
|
153
|
-
with_index Post, :user_id do
|
154
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"]}))
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it "should include index name" do
|
159
|
-
with_index Post, :user_id, :name => "custom_name" do
|
160
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "custom_name"}))
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
it "should define unique index" do
|
165
|
-
with_index Post, :user_id, :name => "posts_user_id_index", :unique => true do
|
166
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "posts_user_id_index", :unique => true}))
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
it "should sort indexes" do
|
171
|
-
with_index Post, :user_id do
|
172
|
-
with_index Post, :short_id do
|
173
|
-
expect(dump_posts).to match(/on_short_id.+on_user_id/m)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
it "should include index order", :mysql => :skip do
|
179
|
-
with_index Post, [:user_id, :first_comment_id, :short_id], :order => { :user_id => :asc, :first_comment_id => :desc } do
|
180
|
-
expect(dump_posts).to match(%r{t.index \["user_id", "first_comment_id", "short_id"\],.*:order => {"user_id" => :asc, "first_comment_id" => :desc, "short_id" => :asc}})
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
context "index extras", :postgresql => :only do
|
185
|
-
|
186
|
-
it "should define case insensitive index" do
|
187
|
-
with_index Post, [:body, :string_no_default], :case_sensitive => false do
|
188
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["body", "string_no_default"], :name => "index_posts_on_body_and_string_no_default", :case_sensitive => false}))
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
it "should define index with type cast" do
|
193
|
-
with_index Post, [:integer_col], :name => "index_with_type_cast", :expression => "LOWER(integer_col::text)" do
|
194
|
-
expect(dump_posts).to match(to_regexp(%q{t.index :name => "index_with_type_cast", :expression => "lower((integer_col)::text)"}))
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
|
199
|
-
it "should define case insensitive index with mixed ids and strings" do
|
200
|
-
with_index Post, [:user_id, :str_short, :short_id, :body], :case_sensitive => false do
|
201
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id", "str_short", "short_id", "body"], :name => "index_posts_on_user_id_and_str_short_and_short_id_and_body", :case_sensitive => false}))
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
[:integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |col_type|
|
206
|
-
col_name = "#{col_type}_col"
|
207
|
-
it "should define case insensitive index that includes an #{col_type}" do
|
208
|
-
with_index Post, [:user_id, :str_short, col_name, :body], :case_sensitive => false do
|
209
|
-
expect(dump_posts).to match(to_regexp(%Q!t.index ["user_id", "str_short", "#{col_name}", "body"], :name => "index_posts_on_user_id_and_str_short_and_#{col_name}_and_body", :case_sensitive => false!))
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should define conditions" do
|
215
|
-
with_index Post, :user_id, :name => "posts_user_id_index", :conditions => "user_id IS NOT NULL" do
|
216
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "posts_user_id_index", :conditions => "(user_id IS NOT NULL)"}))
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
it "should define expression" do
|
221
|
-
with_index Post, :name => "posts_freaky_index", :expression => "USING hash (least(id, user_id))" do
|
222
|
-
expect(dump_posts).to match(to_regexp(%q{t.index :name => "posts_freaky_index", :kind => "hash", :expression => "LEAST(id, user_id)"}))
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
it "should define operator_class" do
|
227
|
-
with_index Post, :body, :operator_class => 'text_pattern_ops' do
|
228
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["body"], :name => "index_posts_on_body", :operator_class => {"body" => "text_pattern_ops"}}))
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
it 'should dump proper operator_class with case_sensitive => false' do
|
233
|
-
with_index Post, :body, :operator_class => 'text_pattern_ops', :case_sensitive => false do
|
234
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["body"], :name => "index_posts_on_body", :case_sensitive => false, :operator_class => {"body" => "text_pattern_ops"}}))
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should dump unique: true with expression (Issue #142)" do
|
239
|
-
with_index Post, :name => "posts_user_body_index", :unique => true, :expression => "BTRIM(LOWER(body))" do
|
240
|
-
expect(dump_posts).to match(%r{#{to_regexp(%q{t.index :name => "posts_user_body_index", :unique => true, :expression => "btrim(lower(body))"})}$})
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
|
245
|
-
it "should not define :case_sensitive => false with non-trivial expression" do
|
246
|
-
with_index Post, :name => "posts_user_body_index", :expression => "BTRIM(LOWER(body))" do
|
247
|
-
expect(dump_posts).to match(%r{#{to_regexp(%q{t.index :name => "posts_user_body_index", :expression => "btrim(lower(body))"})}$})
|
248
|
-
end
|
98
|
+
with_foreign_key Post, :user_id, :users, :id, :on_update => :cascade, :on_delete => :nullify do
|
99
|
+
expect(dump_posts).to match(%q[t.integer\s*"user_id",.*foreign_key: {references: "users", name: "fk_posts_user_id", on_update: :cascade, on_delete: :nullify}])
|
249
100
|
end
|
250
|
-
|
251
|
-
|
252
|
-
it "should define kind" do
|
253
|
-
with_index Post, :name => "posts_body_index", :expression => "USING hash (body)" do
|
254
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["body"], :name => "posts_body_index", :kind => "hash"}))
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
it "should not include index order for non-ordered index types" do
|
259
|
-
with_index Post, :user_id, :kind => :hash do
|
260
|
-
expect(dump_posts).to match(to_regexp(%q{t.index ["user_id"], :name => "index_posts_on_user_id", :kind => "hash"}))
|
261
|
-
expect(dump_posts).not_to match(%r{:order})
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
101
|
end
|
266
102
|
|
267
103
|
context "with cyclic foreign key constraints", :sqlite3 => :skip do
|
268
104
|
before(:all) do
|
269
|
-
ActiveRecord::Base.connection.add_foreign_key(Comment.table_name,
|
270
|
-
ActiveRecord::Base.connection.add_foreign_key(Comment.table_name,
|
271
|
-
ActiveRecord::Base.connection.add_foreign_key(Post.table_name,
|
272
|
-
ActiveRecord::Base.connection.add_foreign_key(Post.table_name,
|
273
|
-
ActiveRecord::Base.connection.add_foreign_key(User.table_name,
|
105
|
+
ActiveRecord::Base.connection.add_foreign_key(Comment.table_name, User.table_name, column: :commenter_id)
|
106
|
+
ActiveRecord::Base.connection.add_foreign_key(Comment.table_name, Post.table_name, column: :post_id)
|
107
|
+
ActiveRecord::Base.connection.add_foreign_key(Post.table_name, Comment.table_name, column: :first_comment_id)
|
108
|
+
ActiveRecord::Base.connection.add_foreign_key(Post.table_name, User.table_name, column: :user_id)
|
109
|
+
ActiveRecord::Base.connection.add_foreign_key(User.table_name, Post.table_name, column: :first_post_id)
|
274
110
|
end
|
275
111
|
|
276
112
|
it "should not raise an error" do
|
@@ -278,124 +114,17 @@ describe "Schema dump" do
|
|
278
114
|
end
|
279
115
|
|
280
116
|
it "should dump constraints after the tables they reference" do
|
281
|
-
expect(dump_schema).to match(%r{create_table "comments".*foreign_key
|
282
|
-
expect(dump_schema).to match(%r{create_table "posts".*foreign_key
|
283
|
-
expect(dump_schema).to match(%r{create_table "posts".*
|
284
|
-
expect(dump_schema).to match(%r{create_table "users".*
|
285
|
-
expect(dump_schema).to match(%r{create_table "users".*
|
286
|
-
end
|
287
|
-
|
288
|
-
context 'with complicated schemas' do
|
289
|
-
before(:all) do
|
290
|
-
|
291
|
-
SchemaPlus.setup do |config|
|
292
|
-
config.foreign_keys.auto_create = false
|
293
|
-
end
|
294
|
-
ActiveRecord::Migration.suppress_messages do
|
295
|
-
ActiveRecord::Schema.define do
|
296
|
-
connection.tables.each do |table| drop_table table, :cascade => true end
|
297
|
-
|
298
|
-
create_table :period_types, force: true do |t|
|
299
|
-
t.string :name
|
300
|
-
end
|
301
|
-
|
302
|
-
create_table :grade_systems, force: true do |t|
|
303
|
-
t.string :name
|
304
|
-
t.integer :school_id
|
305
|
-
t.integer :parent_id
|
306
|
-
t.integer :profile_id
|
307
|
-
end
|
308
|
-
|
309
|
-
create_table :schools, force: true do |t|
|
310
|
-
t.string :name
|
311
|
-
t.integer :default_grade_system_id
|
312
|
-
end
|
313
|
-
|
314
|
-
create_table :academic_years, force: true do |t|
|
315
|
-
t.string :name
|
316
|
-
t.integer :school_id
|
317
|
-
t.integer :period_type_id
|
318
|
-
end
|
319
|
-
|
320
|
-
create_table :buildings, force: true do |t|
|
321
|
-
t.string :name
|
322
|
-
t.integer :school_id
|
323
|
-
end
|
324
|
-
|
325
|
-
create_table :publishing_houses, force: true do |t|
|
326
|
-
t.string :name
|
327
|
-
end
|
328
|
-
|
329
|
-
create_table :profiles, force: true do |t|
|
330
|
-
t.integer :school_id
|
331
|
-
t.integer :publishing_house_id
|
332
|
-
t.integer :building_id
|
333
|
-
end
|
334
|
-
|
335
|
-
create_table :class_units, force: true do |t|
|
336
|
-
t.string :name
|
337
|
-
t.integer :school_id
|
338
|
-
t.integer :mentor_id
|
339
|
-
t.integer :building_id
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
class ::AcademicYear < ActiveRecord::Base ; end
|
345
|
-
class ::Building < ActiveRecord::Base ; end
|
346
|
-
class ::ClassUnit < ActiveRecord::Base ; end
|
347
|
-
class ::GradeSystem < ActiveRecord::Base ; end
|
348
|
-
class ::Profile < ActiveRecord::Base ; end
|
349
|
-
class ::PublishingHouse < ActiveRecord::Base ; end
|
350
|
-
class ::PeriodType < ActiveRecord::Base ; end
|
351
|
-
class ::School < ActiveRecord::Base ; end
|
352
|
-
|
353
|
-
ActiveRecord::Base.connection.add_foreign_key(School.table_name, :default_grade_system_id, GradeSystem.table_name, :id)
|
354
|
-
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :school_id, School.table_name, :id)
|
355
|
-
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :parent_id, GradeSystem.table_name, :id)
|
356
|
-
ActiveRecord::Base.connection.add_foreign_key(GradeSystem.table_name, :profile_id, Profile.table_name, :id)
|
357
|
-
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :building_id, Building.table_name, :id)
|
358
|
-
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :school_id, School.table_name, :id)
|
359
|
-
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :school_id, School.table_name, :id)
|
360
|
-
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :building_id, Building.table_name, :id)
|
361
|
-
ActiveRecord::Base.connection.add_foreign_key(ClassUnit.table_name, :mentor_id, Profile.table_name, :id)
|
362
|
-
ActiveRecord::Base.connection.add_foreign_key(Building.table_name, :school_id, School.table_name, :id)
|
363
|
-
ActiveRecord::Base.connection.add_foreign_key(AcademicYear.table_name, :school_id, School.table_name, :id)
|
364
|
-
ActiveRecord::Base.connection.add_foreign_key(AcademicYear.table_name, :period_type_id, PeriodType.table_name, :id)
|
365
|
-
ActiveRecord::Base.connection.add_foreign_key(Profile.table_name, :publishing_house_id, PublishingHouse.table_name, :id)
|
366
|
-
end
|
367
|
-
|
368
|
-
it "should not raise an error" do
|
369
|
-
expect { dump_schema }.to_not raise_error
|
370
|
-
end
|
371
|
-
|
372
|
-
it "should dump each constraint after both related tables were defined" do
|
373
|
-
expect(dump_schema.scan(%r{add_foreign_key}m).count).to eq 1
|
374
|
-
expect(dump_schema).to match(%r{create_table "schools".*add_foreign_key\s+"schools".*\["default_grade_system_id"\], "grade_systems", \["id"\]}m)
|
375
|
-
expect(dump_schema).to match(%r{create_table "grade_systems".*add_foreign_key\s+"schools".*\["default_grade_system_id"\], "grade_systems", \["id"\]}m)
|
376
|
-
end
|
117
|
+
expect(dump_schema).to match(%r{create_table "comments"(.|\n)*first_comment_id.*foreign_key.*comments})
|
118
|
+
expect(dump_schema).to match(%r{create_table "posts"(.|\n)*first_post_id.*foreign_key.*posts})
|
119
|
+
expect(dump_schema).to match(%r{create_table "posts"(.|\n)*add_foreign_key.*posts.*post_id})
|
120
|
+
expect(dump_schema).to match(%r{create_table "users"(.|\n)*add_foreign_key.*users.*commenter_id})
|
121
|
+
expect(dump_schema).to match(%r{create_table "users"(.|\n)*foreign_key.*users.*user_id})
|
377
122
|
end
|
378
|
-
end
|
379
|
-
|
380
|
-
context 'with enum', :postgresql => :only do
|
381
|
-
let(:connection) { ActiveRecord::Base.connection }
|
382
123
|
|
383
|
-
it
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
ensure
|
388
|
-
connection.execute "DROP TYPE color"
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
it 'should include enum with schema' do
|
393
|
-
begin
|
394
|
-
connection.execute "CREATE SCHEMA cmyk; CREATE TYPE cmyk.color AS ENUM ('cyan', 'magenta', 'yellow', 'black')"
|
395
|
-
expect(dump_schema).to match(%r{create_enum "color", "cyan", "magenta", "yellow", "black", :schema => "cmyk"})
|
396
|
-
ensure
|
397
|
-
connection.execute "DROP SCHEMA cmyk CASCADE"
|
398
|
-
end
|
124
|
+
it "should dump comments for delayed constraint definitions" do
|
125
|
+
expect(dump_schema).to match(%r{"post_id".*# foreign key references "posts"})
|
126
|
+
expect(dump_schema).to match(%r{"commenter_id".*# foreign key references "users"})
|
127
|
+
expect(dump_schema).to match(%r{"user_id".*# foreign key references "users"})
|
399
128
|
end
|
400
129
|
end
|
401
130
|
|
@@ -404,19 +133,6 @@ describe "Schema dump" do
|
|
404
133
|
Regexp.new(Regexp.escape(string))
|
405
134
|
end
|
406
135
|
|
407
|
-
def with_additional_column(model, column_name, column_type, options)
|
408
|
-
table_columns = model.columns.reject{|column| column.name == 'id'}
|
409
|
-
ActiveRecord::Migration.suppress_messages do
|
410
|
-
ActiveRecord::Migration.create_table model.table_name, :force => true do |t|
|
411
|
-
table_columns.each do |column|
|
412
|
-
t.column column.name, column.type, :default => column.default
|
413
|
-
end
|
414
|
-
t.column column_name, column_type, options
|
415
|
-
end
|
416
|
-
end
|
417
|
-
yield
|
418
|
-
end
|
419
|
-
|
420
136
|
def with_foreign_key(model, columns, referenced_table_name, referenced_columns, options = {}, &block)
|
421
137
|
with_foreign_keys(model, [[columns, referenced_table_name, referenced_columns, options]], &block)
|
422
138
|
end
|
@@ -429,7 +145,7 @@ describe "Schema dump" do
|
|
429
145
|
t.column column.name, column.type
|
430
146
|
end
|
431
147
|
columnsets.each do |columns, referenced_table_name, referenced_columns, options|
|
432
|
-
t.foreign_key columns, referenced_table_name,
|
148
|
+
t.foreign_key columns, referenced_table_name, (options||{}).merge(column: referenced_columns)
|
433
149
|
end
|
434
150
|
end
|
435
151
|
end
|
@@ -447,30 +163,9 @@ describe "Schema dump" do
|
|
447
163
|
end
|
448
164
|
end
|
449
165
|
|
450
|
-
def with_index(model, columns, options = {})
|
451
|
-
ActiveRecord::Migration.suppress_messages do
|
452
|
-
ActiveRecord::Migration.add_index(model.table_name, columns, options)
|
453
|
-
end
|
454
|
-
model.reset_column_information
|
455
|
-
begin
|
456
|
-
yield
|
457
|
-
ensure
|
458
|
-
ActiveRecord::Migration.suppress_messages do
|
459
|
-
ActiveRecord::Migration.remove_index(model.table_name, :name => determine_index_name(model, columns, options))
|
460
|
-
end
|
461
|
-
end
|
462
|
-
end
|
463
|
-
|
464
|
-
def determine_index_name(model, columns, options)
|
465
|
-
name = columns[:name] if columns.is_a?(Hash)
|
466
|
-
name ||= options[:name]
|
467
|
-
name ||= model.indexes.detect { |index| index.table == model.table_name.to_s && index.columns.sort == Array(columns).collect(&:to_s).sort }.name
|
468
|
-
name
|
469
|
-
end
|
470
|
-
|
471
166
|
def determine_foreign_key_name(model, columns, options)
|
472
167
|
name = options[:name]
|
473
|
-
name ||= model.foreign_keys.detect { |fk| fk.
|
168
|
+
name ||= model.foreign_keys.detect { |fk| fk.from_table == model.table_name.to_s && Array.wrap(fk.column) == Array.wrap(columns).collect(&:to_s) }.name
|
474
169
|
end
|
475
170
|
|
476
171
|
def dump_schema(opts={})
|