schema_plus_foreign_keys 0.1.0
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 +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
|