schema_plus_foreign_keys 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +21 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +200 -0
- data/Rakefile +9 -0
- data/gemfiles/Gemfile.base +4 -0
- data/gemfiles/activerecord-4.2.0/Gemfile.base +3 -0
- data/gemfiles/activerecord-4.2.0/Gemfile.mysql2 +10 -0
- data/gemfiles/activerecord-4.2.0/Gemfile.postgresql +10 -0
- data/gemfiles/activerecord-4.2.0/Gemfile.sqlite3 +10 -0
- data/gemfiles/activerecord-4.2.1/Gemfile.base +3 -0
- data/gemfiles/activerecord-4.2.1/Gemfile.mysql2 +10 -0
- data/gemfiles/activerecord-4.2.1/Gemfile.postgresql +10 -0
- data/gemfiles/activerecord-4.2.1/Gemfile.sqlite3 +10 -0
- data/lib/schema_plus/foreign_keys.rb +78 -0
- data/lib/schema_plus/foreign_keys/active_record/base.rb +33 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb +168 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/foreign_key_definition.rb +137 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/mysql2_adapter.rb +126 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/postgresql_adapter.rb +89 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/sqlite3_adapter.rb +77 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/table_definition.rb +108 -0
- data/lib/schema_plus/foreign_keys/active_record/migration/command_recorder.rb +29 -0
- data/lib/schema_plus/foreign_keys/middleware/dumper.rb +88 -0
- data/lib/schema_plus/foreign_keys/middleware/migration.rb +147 -0
- data/lib/schema_plus/foreign_keys/middleware/model.rb +15 -0
- data/lib/schema_plus/foreign_keys/middleware/mysql.rb +20 -0
- data/lib/schema_plus/foreign_keys/middleware/sql.rb +27 -0
- data/lib/schema_plus/foreign_keys/version.rb +5 -0
- data/lib/schema_plus_foreign_keys.rb +1 -0
- data/schema_dev.yml +9 -0
- data/schema_plus_foreign_keys.gemspec +31 -0
- data/spec/deprecation_spec.rb +161 -0
- data/spec/foreign_key_definition_spec.rb +34 -0
- data/spec/foreign_key_spec.rb +207 -0
- data/spec/migration_spec.rb +570 -0
- data/spec/named_schemas_spec.rb +136 -0
- data/spec/schema_dumper_spec.rb +257 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/reference.rb +79 -0
- metadata +221 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
module SchemaPlus::ForeignKeys
|
2
|
+
module Middleware
|
3
|
+
|
4
|
+
module Mysql
|
5
|
+
module Migration
|
6
|
+
module DropTable
|
7
|
+
|
8
|
+
def around(env)
|
9
|
+
if (env.options[:force] == :cascade)
|
10
|
+
env.connection.reverse_foreign_keys(env.table_name).each do |foreign_key|
|
11
|
+
env.connection.remove_foreign_key(foreign_key.from_table, name: foreign_key.name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
yield env
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SchemaPlus::ForeignKeys
|
2
|
+
module Middleware
|
3
|
+
module Sql
|
4
|
+
module Table
|
5
|
+
def after(env)
|
6
|
+
foreign_keys = case ::ActiveRecord.version
|
7
|
+
when Gem::Version.new("4.2.0") then env.table_definition.foreign_keys
|
8
|
+
else env.table_definition.foreign_keys.values.tap { |v| v.flatten! }
|
9
|
+
end
|
10
|
+
|
11
|
+
# create foreign key constraints inline in table definition
|
12
|
+
env.sql.body = ([env.sql.body] + foreign_keys.map(&:to_sql)).join(', ')
|
13
|
+
|
14
|
+
# prevents AR >= 4.2.1 from emitting add_foreign_key after the table
|
15
|
+
env.table_definition.foreign_keys.clear
|
16
|
+
end
|
17
|
+
|
18
|
+
module SQLite3
|
19
|
+
|
20
|
+
def before(env)
|
21
|
+
env.connection.execute('PRAGMA FOREIGN_KEYS = ON') if env.table_definition.foreign_keys.any?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'schema_plus/foreign_keys'
|
data/schema_dev.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'schema_plus/foreign_keys/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "schema_plus_foreign_keys"
|
8
|
+
gem.version = SchemaPlus::ForeignKeys::VERSION
|
9
|
+
gem.authors = ["ronen barzel"]
|
10
|
+
gem.email = ["ronen@barzel.org"]
|
11
|
+
gem.summary = %q{Extended support for foreign key constraints in ActiveRecord}
|
12
|
+
gem.description = %q{Extended support for foreign key constraints in ActiveRecord, including: definition as column attribute; deferrable; and SQLite3 support; cleaner dumps; and more!}
|
13
|
+
gem.homepage = "https://github.com/SchemaPlus/schema_plus_foreign_keys"
|
14
|
+
gem.license = "MIT"
|
15
|
+
|
16
|
+
gem.files = `git ls-files -z`.split("\x0")
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_dependency "activerecord", "~> 4.2"
|
22
|
+
gem.add_dependency "schema_plus_core", "~> 0.4"
|
23
|
+
gem.add_dependency "valuable"
|
24
|
+
|
25
|
+
gem.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
gem.add_development_dependency "rake", "~> 10.0"
|
27
|
+
gem.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
gem.add_development_dependency "schema_dev", "~> 3.5"
|
29
|
+
gem.add_development_dependency "simplecov"
|
30
|
+
gem.add_development_dependency "simplecov-gem-profile"
|
31
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Deprecations' do
|
4
|
+
|
5
|
+
let(:migration) { ActiveRecord::Migration }
|
6
|
+
|
7
|
+
describe "on add_foreign_key", sqlite3: :skip do
|
8
|
+
before(:each) do
|
9
|
+
define_schema do
|
10
|
+
create_table :posts
|
11
|
+
create_table :comments do |t|
|
12
|
+
t.integer :post_id
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Comment < ::ActiveRecord::Base ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "deprecates 4-argument form" do
|
19
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/4-argument/)
|
20
|
+
migration.add_foreign_key "comments", "post_id", "posts", "id"
|
21
|
+
expect(Comment).to reference(:posts, :id).on(:post_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "on remove_foreign_key", sqlite3: :skip do
|
27
|
+
before(:each) do
|
28
|
+
define_schema do
|
29
|
+
create_table :posts
|
30
|
+
create_table :comments do |t|
|
31
|
+
t.integer :post_id, foreign_key: true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class Comment < ::ActiveRecord::Base ; end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "deprecates :column_names option" do
|
38
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/column_names/)
|
39
|
+
migration.remove_foreign_key "comments", "posts", column_names: "post_id"
|
40
|
+
Comment.reset_column_information
|
41
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "deprecates :references_column_names option" do
|
45
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/references_column_names.*primary_key/)
|
46
|
+
migration.remove_foreign_key "comments", "posts", references_column_names: "id"
|
47
|
+
Comment.reset_column_information
|
48
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "deprecates :references_table_name option" do
|
52
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/references_table_name.*to_table/)
|
53
|
+
migration.remove_foreign_key "comments", references_table_name: "posts"
|
54
|
+
Comment.reset_column_information
|
55
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "deprecates table-and-name form" do
|
59
|
+
Comment.reset_column_information
|
60
|
+
name = Comment.foreign_keys.first.name
|
61
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/name.*name: name/)
|
62
|
+
migration.remove_foreign_key "comments", name
|
63
|
+
Comment.reset_column_information
|
64
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "deprecates 3-argument form" do
|
68
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/3.*-argument/)
|
69
|
+
migration.remove_foreign_key "comments", "post_id", "posts"
|
70
|
+
Comment.reset_column_information
|
71
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "deprecates 4-argument form" do
|
75
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/4.*-argument/)
|
76
|
+
migration.remove_foreign_key "comments", "post_id", "posts", "id"
|
77
|
+
Comment.reset_column_information
|
78
|
+
expect(Comment).to_not reference(:posts, :id).on(:post_id)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "raises error for 5 arguments" do
|
82
|
+
expect { migration.remove_foreign_key "zip", "a", "dee", "do", "da" }.to raise_error /Wrong number of arguments.*5/
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "on foreign key definition" do
|
88
|
+
before(:each) do
|
89
|
+
define_schema do
|
90
|
+
create_table :posts
|
91
|
+
create_table :comments do |t|
|
92
|
+
t.integer :post_id, foreign_key: true
|
93
|
+
end
|
94
|
+
end
|
95
|
+
class Comment < ::ActiveRecord::Base ; end
|
96
|
+
end
|
97
|
+
|
98
|
+
let(:definition) {
|
99
|
+
Comment.reset_column_information
|
100
|
+
Comment.foreign_keys.first
|
101
|
+
}
|
102
|
+
|
103
|
+
it "deprecates column_names" do
|
104
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/column_names/)
|
105
|
+
expect(definition.column_names).to eq(["post_id"])
|
106
|
+
end
|
107
|
+
|
108
|
+
it "deprecates references_column_names" do
|
109
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/references_column_names.*primary_key/)
|
110
|
+
expect(definition.references_column_names).to eq(["id"])
|
111
|
+
end
|
112
|
+
|
113
|
+
it "deprecates references_table_name" do
|
114
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/references_table_name.*to_table/)
|
115
|
+
expect(definition.references_table_name).to eq("posts")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "deprecates table_name" do
|
119
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/table_name.*from_table/)
|
120
|
+
expect(definition.table_name).to eq("comments")
|
121
|
+
end
|
122
|
+
|
123
|
+
it "deprecates :set_null" do
|
124
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/set_null.*nullify/)
|
125
|
+
define_schema do
|
126
|
+
create_table :posts
|
127
|
+
create_table :comments do |t|
|
128
|
+
t.integer :post_id, references: :posts, on_delete: :set_null
|
129
|
+
end
|
130
|
+
end
|
131
|
+
expect(definition.on_delete).to eq(:nullify)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "in table definition" do
|
137
|
+
it "deprecates 3-column form" do
|
138
|
+
expect(ActiveSupport::Deprecation).to receive(:warn).with(/positional arg.*primary_key/)
|
139
|
+
define_schema do
|
140
|
+
create_table :posts, primary_key: :funky
|
141
|
+
create_table :comments do |t|
|
142
|
+
t.integer :post_id
|
143
|
+
t.foreign_key :post_id, :posts, :funky
|
144
|
+
end
|
145
|
+
end
|
146
|
+
expect(migration.foreign_keys("comments").first.primary_key).to eq("funky")
|
147
|
+
end
|
148
|
+
|
149
|
+
it "raises error for 4 arguments" do
|
150
|
+
expect {
|
151
|
+
define_schema do
|
152
|
+
create_table :posts, primary_key: :funky
|
153
|
+
create_table :comments do |t|
|
154
|
+
t.integer :post_id
|
155
|
+
t.foreign_key :post_id, :posts, :funky, :town
|
156
|
+
end
|
157
|
+
end
|
158
|
+
}.to raise_error /wrong number of arguments/i
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Foreign Key definition" do
|
4
|
+
|
5
|
+
let(:definition) {
|
6
|
+
options = {:name => "posts_user_fkey", :column => :user, :primary_key => :id}
|
7
|
+
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(:posts, :users, options)
|
8
|
+
}
|
9
|
+
|
10
|
+
it "dumps to sql with quoted values" do
|
11
|
+
expect(definition.to_sql).to eq(%Q{CONSTRAINT posts_user_fkey FOREIGN KEY (#{quote_column_name('user')}) REFERENCES #{quote_table_name('users')} (#{quote_column_name('id')})})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "dumps to sql with deferrable values" do
|
15
|
+
options = {:name => "posts_user_fkey", :column => :user, :primary_key => :id, :deferrable => true}
|
16
|
+
deferred_definition = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(:posts, :users, options)
|
17
|
+
expect(deferred_definition.to_sql).to eq(%Q{CONSTRAINT posts_user_fkey FOREIGN KEY (#{quote_column_name('user')}) REFERENCES #{quote_table_name('users')} (#{quote_column_name('id')}) DEFERRABLE})
|
18
|
+
end
|
19
|
+
|
20
|
+
it "dumps to sql with initially deferrable values" do
|
21
|
+
options = {:name => "posts_user_fkey", :column => :user, :primary_key => :id, :deferrable => :initially_deferred}
|
22
|
+
initially_deferred_definition = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(:posts, :users, options)
|
23
|
+
expect(initially_deferred_definition.to_sql).to eq(%Q{CONSTRAINT posts_user_fkey FOREIGN KEY (#{quote_column_name('user')}) REFERENCES #{quote_table_name('users')} (#{quote_column_name('id')}) DEFERRABLE INITIALLY DEFERRED})
|
24
|
+
end
|
25
|
+
|
26
|
+
def quote_table_name(table)
|
27
|
+
ActiveRecord::Base.connection.quote_table_name(table)
|
28
|
+
end
|
29
|
+
|
30
|
+
def quote_column_name(column)
|
31
|
+
ActiveRecord::Base.connection.quote_column_name(column)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Foreign Key" do
|
4
|
+
|
5
|
+
let(:migration) { ::ActiveRecord::Migration }
|
6
|
+
|
7
|
+
context "created with table" do
|
8
|
+
before(:each) do
|
9
|
+
define_schema do
|
10
|
+
create_table :users, :force => true do |t|
|
11
|
+
t.string :login
|
12
|
+
end
|
13
|
+
create_table :comments, :force => true do |t|
|
14
|
+
t.integer :user_id
|
15
|
+
t.foreign_key :user_id, :users
|
16
|
+
end
|
17
|
+
end
|
18
|
+
class User < ::ActiveRecord::Base ; end
|
19
|
+
class Comment < ::ActiveRecord::Base ; end
|
20
|
+
Comment.reset_column_information
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should report foreign key constraints" do
|
24
|
+
expect(Comment.foreign_keys.collect(&:column).flatten).to eq([ "user_id" ])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should report reverse foreign key constraints" do
|
28
|
+
expect(User.reverse_foreign_keys.collect(&:column).flatten).to eq([ "user_id" ])
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context "modification" do
|
34
|
+
|
35
|
+
before(:each) do
|
36
|
+
define_schema do
|
37
|
+
create_table :users, :force => true do |t|
|
38
|
+
t.string :login
|
39
|
+
t.datetime :deleted_at
|
40
|
+
end
|
41
|
+
|
42
|
+
create_table :posts, :force => true do |t|
|
43
|
+
t.text :body
|
44
|
+
t.integer :user_id
|
45
|
+
t.integer :author_id
|
46
|
+
end
|
47
|
+
|
48
|
+
create_table :comments, :force => true do |t|
|
49
|
+
t.text :body
|
50
|
+
t.integer :post_id
|
51
|
+
t.foreign_key :post_id, :posts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
class User < ::ActiveRecord::Base ; end
|
55
|
+
class Post < ::ActiveRecord::Base ; end
|
56
|
+
class Comment < ::ActiveRecord::Base ; end
|
57
|
+
Comment.reset_column_information
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
context "works", :sqlite3 => :skip do
|
62
|
+
|
63
|
+
context "when is added", "posts(author_id)" do
|
64
|
+
|
65
|
+
before(:each) do
|
66
|
+
add_foreign_key(:posts, :users, :column => :author_id, :on_update => :cascade, :on_delete => :restrict)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "references users(id)" do
|
70
|
+
expect(Post).to reference(:users, :id).on(:author_id)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "cascades on update" do
|
74
|
+
expect(Post).to reference(:users).on_update(:cascade)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "restricts on delete" do
|
78
|
+
expect(Post).to reference(:users).on_delete(:restrict)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "is available in Post.foreign_keys" do
|
82
|
+
expect(Post.foreign_keys.collect(&:column)).to include('author_id')
|
83
|
+
end
|
84
|
+
|
85
|
+
it "is available in User.reverse_foreign_keys" do
|
86
|
+
expect(User.reverse_foreign_keys.collect(&:column)).to include('author_id')
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when is dropped", "comments(post_id)" do
|
92
|
+
|
93
|
+
let(:foreign_key_name) { fk = Comment.foreign_keys.detect(&its.column == 'post_id') and fk.name }
|
94
|
+
|
95
|
+
before(:each) do
|
96
|
+
remove_foreign_key(:comments, name: foreign_key_name)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "doesn't reference posts(id)" do
|
100
|
+
expect(Comment).not_to reference(:posts).on(:post_id)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "is no longer available in Post.foreign_keys" do
|
104
|
+
expect(Comment.foreign_keys.collect(&:column)).not_to include('post_id')
|
105
|
+
end
|
106
|
+
|
107
|
+
it "is no longer available in User.reverse_foreign_keys" do
|
108
|
+
expect(Post.reverse_foreign_keys.collect(&:column)).not_to include('post_id')
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when drop using hash", "comments(post_id)" do
|
114
|
+
|
115
|
+
let(:foreign_key_name) { fk = Comment.foreign_keys.detect(&its.column == 'post_id') and fk.name }
|
116
|
+
|
117
|
+
it "finds by name" do
|
118
|
+
remove_foreign_key(:comments, name: foreign_key_name)
|
119
|
+
expect(Comment).not_to reference(:posts).on(:post_id)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "finds by column_names" do
|
123
|
+
remove_foreign_key(:comments, column: "post_id", to_table: "posts")
|
124
|
+
expect(Comment).not_to reference(:posts).on(:post_id)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when attempt to drop nonexistent foreign key" do
|
129
|
+
it "raises error" do
|
130
|
+
expect{remove_foreign_key(:comments, "posts", column: "nonesuch")}.to raise_error(/no foreign key/i)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "does not error with :if_exists" do
|
134
|
+
expect{remove_foreign_key(:comments, "posts", column: "nonesuch", :if_exists => true)}.to_not raise_error
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when referencing column and column is removed" do
|
139
|
+
|
140
|
+
let(:foreign_key_name) { Comment.foreign_keys.detect { |definition| definition.column == 'post_id' }.name }
|
141
|
+
|
142
|
+
it "should remove foreign keys" do
|
143
|
+
remove_foreign_key(:comments, name: foreign_key_name)
|
144
|
+
expect(Post.reverse_foreign_keys.collect { |fk| fk.column == 'post_id' && fk.from_table == "comments" }).to be_empty
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when table name is a reserved word" do
|
150
|
+
before(:each) do
|
151
|
+
migration.suppress_messages do
|
152
|
+
migration.create_table :references, :force => true do |t|
|
153
|
+
t.integer :post_id, :foreign_key => false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it "can add, detect, and remove a foreign key without error" do
|
159
|
+
migration.suppress_messages do
|
160
|
+
expect {
|
161
|
+
migration.add_foreign_key(:references, :posts)
|
162
|
+
foreign_key = migration.foreign_keys(:references).detect{|definition| definition.column == "post_id"}
|
163
|
+
migration.remove_foreign_key(:references, name: foreign_key.name)
|
164
|
+
}.to_not raise_error
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
context "raises an exception", :sqlite3 => :only do
|
172
|
+
|
173
|
+
it "when attempting to add" do
|
174
|
+
expect {
|
175
|
+
add_foreign_key(:posts, :users, :column => :author_id, :on_update => :cascade, :on_delete => :restrict)
|
176
|
+
}.to raise_error(NotImplementedError)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "when attempting to remove" do
|
180
|
+
expect {
|
181
|
+
remove_foreign_key(:posts, name: "dummy")
|
182
|
+
}.to raise_error(NotImplementedError)
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
protected
|
189
|
+
def add_foreign_key(*args)
|
190
|
+
migration.suppress_messages do
|
191
|
+
migration.add_foreign_key(*args)
|
192
|
+
end
|
193
|
+
User.reset_column_information
|
194
|
+
Post.reset_column_information
|
195
|
+
Comment.reset_column_information
|
196
|
+
end
|
197
|
+
|
198
|
+
def remove_foreign_key(*args)
|
199
|
+
migration.suppress_messages do
|
200
|
+
migration.remove_foreign_key(*args)
|
201
|
+
end
|
202
|
+
User.reset_column_information
|
203
|
+
Post.reset_column_information
|
204
|
+
Comment.reset_column_information
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|