schema_plus_foreign_keys 0.1.8 → 1.0.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 +4 -4
- data/.github/workflows/prs.yml +134 -0
- data/.gitignore +1 -0
- data/.simplecov +20 -0
- data/Gemfile +4 -1
- data/README.md +25 -18
- data/Rakefile +3 -1
- data/gemfiles/Gemfile.base +1 -1
- data/gemfiles/activerecord-5.2/Gemfile.base +2 -1
- data/gemfiles/activerecord-5.2/Gemfile.mysql2 +2 -2
- data/gemfiles/activerecord-5.2/Gemfile.postgresql +2 -2
- data/gemfiles/activerecord-5.2/Gemfile.sqlite3 +3 -3
- data/gemfiles/activerecord-6.0/Gemfile.base +4 -0
- data/gemfiles/activerecord-6.0/Gemfile.mysql2 +10 -0
- data/gemfiles/activerecord-6.0/Gemfile.postgresql +10 -0
- data/gemfiles/{activerecord-4.2.0 → activerecord-6.0}/Gemfile.sqlite3 +3 -3
- data/lib/schema_plus/foreign_keys/active_record/base.rb +2 -0
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract/schema_creation.rb +2 -11
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract_adapter.rb +7 -47
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/foreign_key_definition.rb +4 -35
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/mysql2_adapter.rb +15 -16
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/postgresql_adapter.rb +8 -6
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/sqlite3_adapter.rb +8 -6
- data/lib/schema_plus/foreign_keys/active_record/connection_adapters/table_definition.rb +7 -46
- data/lib/schema_plus/foreign_keys/active_record/migration/command_recorder.rb +4 -2
- data/lib/schema_plus/foreign_keys/middleware/dumper.rb +4 -2
- data/lib/schema_plus/foreign_keys/middleware/migration.rb +13 -5
- data/lib/schema_plus/foreign_keys/middleware/model.rb +2 -0
- data/lib/schema_plus/foreign_keys/middleware/mysql.rb +3 -1
- data/lib/schema_plus/foreign_keys/middleware/sql.rb +2 -16
- data/lib/schema_plus/foreign_keys/version.rb +3 -1
- data/lib/schema_plus/foreign_keys.rb +2 -1
- data/lib/schema_plus_foreign_keys.rb +2 -0
- data/schema_dev.yml +4 -6
- data/schema_plus_foreign_keys.gemspec +10 -9
- data/spec/deprecation_spec.rb +11 -110
- data/spec/foreign_key_definition_spec.rb +5 -3
- data/spec/foreign_key_spec.rb +22 -20
- data/spec/migration_spec.rb +35 -59
- data/spec/named_schemas_spec.rb +16 -14
- data/spec/schema_dumper_spec.rb +13 -13
- data/spec/spec_helper.rb +4 -2
- data/spec/support/reference.rb +3 -2
- metadata +31 -89
- data/.travis.yml +0 -33
- data/gemfiles/activerecord-4.2.0/Gemfile.base +0 -3
- data/gemfiles/activerecord-4.2.0/Gemfile.mysql2 +0 -10
- data/gemfiles/activerecord-4.2.0/Gemfile.postgresql +0 -10
- data/gemfiles/activerecord-4.2.1/Gemfile.base +0 -3
- data/gemfiles/activerecord-4.2.1/Gemfile.mysql2 +0 -10
- data/gemfiles/activerecord-4.2.1/Gemfile.postgresql +0 -10
- data/gemfiles/activerecord-4.2.1/Gemfile.sqlite3 +0 -10
- data/gemfiles/activerecord-4.2.6/Gemfile.base +0 -3
- data/gemfiles/activerecord-4.2.6/Gemfile.mysql2 +0 -10
- data/gemfiles/activerecord-4.2.6/Gemfile.postgresql +0 -10
- data/gemfiles/activerecord-4.2.6/Gemfile.sqlite3 +0 -10
- data/gemfiles/activerecord-5.0/Gemfile.base +0 -3
- data/gemfiles/activerecord-5.0/Gemfile.mysql2 +0 -10
- data/gemfiles/activerecord-5.0/Gemfile.postgresql +0 -10
- data/gemfiles/activerecord-5.0/Gemfile.sqlite3 +0 -10
- data/gemfiles/activerecord-5.1/Gemfile.base +0 -3
- data/gemfiles/activerecord-5.1/Gemfile.mysql2 +0 -10
- data/gemfiles/activerecord-5.1/Gemfile.postgresql +0 -10
- data/gemfiles/activerecord-5.1/Gemfile.sqlite3 +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4320accfc977e0693af01ea8da225767890fe058a20e2fb38a5b3e17d96e5f8a
|
|
4
|
+
data.tar.gz: 7bb518bae024a887cefc969ec98b0c6b8c79f6818386e04362fe294622c7596c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8378363061d53b5f479c12e333489efb6206f47aaf259e50852346f437cd90662dc3efbbb2c2337ef562a29b5f4d92cdd8e5a3f2e7a8c015f70fdc1c5f2e6f3d
|
|
7
|
+
data.tar.gz: 4a67d8e35b227029cf1af8834d0e387afddded929504a78ccae97a65a0563a8e2bab34f179315a57e8d1990fc1d8544f1cf36cfb2574ec6740a2d92890d74420
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# This file was auto-generated by the schema_dev tool, based on the data in
|
|
2
|
+
# ./schema_dev.yml
|
|
3
|
+
# Please do not edit this file; any changes will be overwritten next time
|
|
4
|
+
# schema_dev gets run.
|
|
5
|
+
---
|
|
6
|
+
name: CI PR Builds
|
|
7
|
+
'on':
|
|
8
|
+
push:
|
|
9
|
+
branches:
|
|
10
|
+
- master
|
|
11
|
+
pull_request:
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
ruby:
|
|
22
|
+
- '2.5'
|
|
23
|
+
- '2.7'
|
|
24
|
+
- '3.0'
|
|
25
|
+
activerecord:
|
|
26
|
+
- '5.2'
|
|
27
|
+
- '6.0'
|
|
28
|
+
db:
|
|
29
|
+
- mysql2
|
|
30
|
+
- sqlite3
|
|
31
|
+
- skip
|
|
32
|
+
dbversion:
|
|
33
|
+
- skip
|
|
34
|
+
exclude:
|
|
35
|
+
- ruby: '3.0'
|
|
36
|
+
activerecord: '5.2'
|
|
37
|
+
- db: skip
|
|
38
|
+
dbversion: skip
|
|
39
|
+
include:
|
|
40
|
+
- ruby: '2.5'
|
|
41
|
+
activerecord: '5.2'
|
|
42
|
+
db: postgresql
|
|
43
|
+
dbversion: '9.6'
|
|
44
|
+
- ruby: '2.5'
|
|
45
|
+
activerecord: '6.0'
|
|
46
|
+
db: postgresql
|
|
47
|
+
dbversion: '9.6'
|
|
48
|
+
- ruby: '2.7'
|
|
49
|
+
activerecord: '5.2'
|
|
50
|
+
db: postgresql
|
|
51
|
+
dbversion: '9.6'
|
|
52
|
+
- ruby: '2.7'
|
|
53
|
+
activerecord: '6.0'
|
|
54
|
+
db: postgresql
|
|
55
|
+
dbversion: '9.6'
|
|
56
|
+
- ruby: '3.0'
|
|
57
|
+
activerecord: '6.0'
|
|
58
|
+
db: postgresql
|
|
59
|
+
dbversion: '9.6'
|
|
60
|
+
env:
|
|
61
|
+
BUNDLE_GEMFILE: "${{ github.workspace }}/gemfiles/activerecord-${{ matrix.activerecord }}/Gemfile.${{ matrix.db }}"
|
|
62
|
+
MYSQL_DB_HOST: 127.0.0.1
|
|
63
|
+
MYSQL_DB_USER: root
|
|
64
|
+
MYSQL_DB_PASS: database
|
|
65
|
+
POSTGRESQL_DB_HOST: 127.0.0.1
|
|
66
|
+
POSTGRESQL_DB_USER: schema_plus_test
|
|
67
|
+
POSTGRESQL_DB_PASS: database
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v2
|
|
70
|
+
- name: Set up Ruby
|
|
71
|
+
uses: ruby/setup-ruby@v1
|
|
72
|
+
with:
|
|
73
|
+
ruby-version: "${{ matrix.ruby }}"
|
|
74
|
+
bundler-cache: true
|
|
75
|
+
- name: Run bundle update
|
|
76
|
+
run: bundle update
|
|
77
|
+
- name: Start Mysql
|
|
78
|
+
if: matrix.db == 'mysql2'
|
|
79
|
+
run: |
|
|
80
|
+
docker run --rm --detach \
|
|
81
|
+
-e MYSQL_ROOT_PASSWORD=$MYSQL_DB_PASS \
|
|
82
|
+
-p 3306:3306 \
|
|
83
|
+
--health-cmd "mysqladmin ping --host=127.0.0.1 --password=$MYSQL_DB_PASS --silent" \
|
|
84
|
+
--health-interval 5s \
|
|
85
|
+
--health-timeout 5s \
|
|
86
|
+
--health-retries 5 \
|
|
87
|
+
--name database mysql:5.6
|
|
88
|
+
- name: Start Postgresql
|
|
89
|
+
if: matrix.db == 'postgresql'
|
|
90
|
+
run: |
|
|
91
|
+
docker run --rm --detach \
|
|
92
|
+
-e POSTGRES_USER=$POSTGRESQL_DB_USER \
|
|
93
|
+
-e POSTGRES_PASSWORD=$POSTGRESQL_DB_PASS \
|
|
94
|
+
-p 5432:5432 \
|
|
95
|
+
--health-cmd "pg_isready -q" \
|
|
96
|
+
--health-interval 5s \
|
|
97
|
+
--health-timeout 5s \
|
|
98
|
+
--health-retries 5 \
|
|
99
|
+
--name database postgres:${{ matrix.dbversion }}
|
|
100
|
+
- name: Wait for database to start
|
|
101
|
+
if: "(matrix.db == 'postgresql' || matrix.db == 'mysql2')"
|
|
102
|
+
run: |
|
|
103
|
+
COUNT=0
|
|
104
|
+
ATTEMPTS=20
|
|
105
|
+
until [[ $COUNT -eq $ATTEMPTS ]]; do
|
|
106
|
+
[ "$(docker inspect -f {{.State.Health.Status}} database)" == "healthy" ] && break
|
|
107
|
+
echo $(( COUNT++ )) > /dev/null
|
|
108
|
+
sleep 2
|
|
109
|
+
done
|
|
110
|
+
- name: Create testing database
|
|
111
|
+
if: "(matrix.db == 'postgresql' || matrix.db == 'mysql2')"
|
|
112
|
+
run: bundle exec rake create_ci_database
|
|
113
|
+
- name: Run tests
|
|
114
|
+
run: bundle exec rake spec
|
|
115
|
+
- name: Shutdown database
|
|
116
|
+
if: always() && (matrix.db == 'postgresql' || matrix.db == 'mysql2')
|
|
117
|
+
run: docker stop database
|
|
118
|
+
- name: Coveralls Parallel
|
|
119
|
+
if: "${{ !env.ACT }}"
|
|
120
|
+
uses: coverallsapp/github-action@master
|
|
121
|
+
with:
|
|
122
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
123
|
+
flag-name: run-${{ matrix.ruby }}-${{ matrix.activerecord }}-${{ matrix.db }}-${{ matrix.dbversion }}
|
|
124
|
+
parallel: true
|
|
125
|
+
finish:
|
|
126
|
+
needs: test
|
|
127
|
+
runs-on: ubuntu-latest
|
|
128
|
+
steps:
|
|
129
|
+
- name: Coveralls Finished
|
|
130
|
+
if: "${{ !env.ACT }}"
|
|
131
|
+
uses: coverallsapp/github-action@master
|
|
132
|
+
with:
|
|
133
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
134
|
+
parallel-finished: true
|
data/.gitignore
CHANGED
data/.simplecov
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
SimpleCov.configure do
|
|
4
|
+
enable_coverage :branch
|
|
5
|
+
add_filter '/spec/'
|
|
6
|
+
|
|
7
|
+
add_group 'Binaries', '/bin/'
|
|
8
|
+
add_group 'Libraries', '/lib/'
|
|
9
|
+
|
|
10
|
+
if ENV['CI']
|
|
11
|
+
require 'simplecov-lcov'
|
|
12
|
+
|
|
13
|
+
SimpleCov::Formatter::LcovFormatter.config do |c|
|
|
14
|
+
c.report_with_single_file = true
|
|
15
|
+
c.single_report_path = 'coverage/lcov.info'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
formatter SimpleCov::Formatter::LcovFormatter
|
|
19
|
+
end
|
|
20
|
+
end
|
data/Gemfile
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source "http://rubygems.org"
|
|
2
4
|
|
|
3
5
|
gemspec
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
gemfile_local = File.expand_path '../Gemfile.local', __FILE__
|
|
8
|
+
eval File.read(gemfile_local), binding, gemfile_local if File.exist? gemfile_local
|
data/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
[](http://badge.fury.io/rb/schema_plus_foreign_keys)
|
|
2
|
-
[](https://github.com/SchemaPlus/schema_plus_foreign_keys/actions)
|
|
3
|
+
[](https://coveralls.io/github/SchemaPlus/schema_plus_foreign_keys)
|
|
4
4
|
|
|
5
5
|
# SchemaPlus::ForeignKeys
|
|
6
6
|
|
|
7
|
-
SchemaPlus::ForeignKeys provides extended support in ActiveRecord. This includes extended support for
|
|
7
|
+
SchemaPlus::ForeignKeys provides extended support in ActiveRecord. This includes extended support for declaring
|
|
8
|
+
foreign key constraints in migrations; support for deferrable constraints; support for SQLite3; cleaner schema dumps.
|
|
8
9
|
|
|
9
|
-
SchemaPlus::ForeignKeys is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord
|
|
10
|
+
SchemaPlus::ForeignKeys is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord
|
|
11
|
+
extension gems.
|
|
10
12
|
|
|
11
|
-
For extra convenience, see also [schema_auto_foreign_keys](https://github.com/SchemaPlus/schema_auto_foreign_keys),
|
|
13
|
+
For extra convenience, see also [schema_auto_foreign_keys](https://github.com/SchemaPlus/schema_auto_foreign_keys),
|
|
14
|
+
which creates foriegn key constraints automatically.
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
@@ -29,7 +32,8 @@ gem.add_dependency "schema_plus_foreign_keys" # in a .gemspec
|
|
|
29
32
|
### Migrations
|
|
30
33
|
|
|
31
34
|
To declare a foreign key constraint for a column, use the `:foreign_key`
|
|
32
|
-
option. The same options can be used with `t.integer`, `t.references`, `t.belongs_to`, `t.foreign_key`,
|
|
35
|
+
option. The same options can be used with `t.integer`, `t.references`, `t.belongs_to`, `t.foreign_key`,
|
|
36
|
+
`change_column`, and `add_foreign_key`:
|
|
33
37
|
|
|
34
38
|
t.references :author, foreign_key: true # create a foreign_key to table "authors"
|
|
35
39
|
t.references :author, foreign_key: {} # create a foreign_key to table "authors"
|
|
@@ -70,7 +74,8 @@ them in a `foreign_key` hash, e.g.
|
|
|
70
74
|
t.references :author, on_delete: :cascade # shorthand for foreign_key: { on_delete: :cascade }
|
|
71
75
|
t.references :author, references: :people # shorthand for foreign_key: { references: :people }
|
|
72
76
|
|
|
73
|
-
To remove a foreign key constraint, you can either change the column, specifying `foreign_key: false`, or
|
|
77
|
+
To remove a foreign key constraint, you can either change the column, specifying `foreign_key: false`, or
|
|
78
|
+
use `migration.remove_foreign_key(table, column)`
|
|
74
79
|
|
|
75
80
|
### Introspection
|
|
76
81
|
|
|
@@ -131,11 +136,14 @@ foreign key options.
|
|
|
131
136
|
|
|
132
137
|
### Schema Dump
|
|
133
138
|
|
|
134
|
-
For clarity (and because it's required for SQLite3), in the generated `schema_dump.rb` file, the foreign key
|
|
139
|
+
For clarity (and because it's required for SQLite3), in the generated `schema_dump.rb` file, the foreign key
|
|
140
|
+
definitions are included within the table definitions.
|
|
135
141
|
|
|
136
142
|
This means that the tables are output sorted that a table is
|
|
137
|
-
defined before others that depend on it. If, however, there are
|
|
138
|
-
foreign key relations, this won't be possible; In that case some table definitions will include comments indicating
|
|
143
|
+
defined before others that depend on it. If, however, there are circular dependencies in the
|
|
144
|
+
foreign key relations, this won't be possible; In that case some table definitions will include comments indicating
|
|
145
|
+
a "forward reference" to a table that's farther down in the file, and the constraint will be defined once that table
|
|
146
|
+
is defined (this can never happen with SQLite3).
|
|
139
147
|
|
|
140
148
|
|
|
141
149
|
## Compatibility
|
|
@@ -144,17 +152,17 @@ SchemaPlus::ForeignKeys is tested on:
|
|
|
144
152
|
|
|
145
153
|
<!-- SCHEMA_DEV: MATRIX - begin -->
|
|
146
154
|
<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
|
|
147
|
-
* ruby **2.
|
|
148
|
-
* ruby **2.
|
|
149
|
-
* ruby **2.
|
|
150
|
-
* ruby **2.
|
|
151
|
-
* ruby **
|
|
152
|
-
* ruby **2.3.1** with activerecord **5.2**, using **mysql2**, **sqlite3** or **postgresql**
|
|
155
|
+
* ruby **2.5** with activerecord **5.2**, using **mysql2**, **sqlite3** or **postgresql:9.6**
|
|
156
|
+
* ruby **2.5** with activerecord **6.0**, using **mysql2**, **sqlite3** or **postgresql:9.6**
|
|
157
|
+
* ruby **2.7** with activerecord **5.2**, using **mysql2**, **sqlite3** or **postgresql:9.6**
|
|
158
|
+
* ruby **2.7** with activerecord **6.0**, using **mysql2**, **sqlite3** or **postgresql:9.6**
|
|
159
|
+
* ruby **3.0** with activerecord **6.0**, using **mysql2**, **sqlite3** or **postgresql:9.6**
|
|
153
160
|
|
|
154
161
|
<!-- SCHEMA_DEV: MATRIX - end -->
|
|
155
162
|
|
|
156
163
|
## History
|
|
157
164
|
|
|
165
|
+
* 1.0.0 - Drop Ruby < 2.5 and Rails < 5.2, adding Rails 6.0, and remove many deprecations
|
|
158
166
|
* 0.1.8 - Compatibility with ActiveRecord 5.1 and ActiveRecord 5.2.
|
|
159
167
|
* 0.1.7 - Compatibility with ActiveRecord 5.0.
|
|
160
168
|
* 0.1.6 - Missing require
|
|
@@ -178,7 +186,7 @@ Some things to know about to help you develop and test:
|
|
|
178
186
|
* **schema_dev**: SchemaPlus::ForeignKeys uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
|
|
179
187
|
facilitate running rspec tests on the matrix of ruby, activerecord, and database
|
|
180
188
|
versions that the gem supports, both locally and on
|
|
181
|
-
[
|
|
189
|
+
[github actions](https://github.com/SchemaPlus/schema_plus_foreign_keys/actions)
|
|
182
190
|
|
|
183
191
|
To to run rspec locally on the full matrix, do:
|
|
184
192
|
|
|
@@ -190,7 +198,6 @@ Some things to know about to help you develop and test:
|
|
|
190
198
|
The matrix of configurations is specified in `schema_dev.yml` in
|
|
191
199
|
the project root.
|
|
192
200
|
|
|
193
|
-
|
|
194
201
|
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
|
|
195
202
|
|
|
196
203
|
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
|
data/Rakefile
CHANGED
data/gemfiles/Gemfile.base
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
eval
|
|
1
|
+
base_gemfile = File.expand_path('../Gemfile.base', __FILE__)
|
|
2
|
+
eval File.read(base_gemfile), binding, base_gemfile
|
|
3
3
|
|
|
4
4
|
platform :ruby do
|
|
5
5
|
gem "sqlite3"
|
|
@@ -7,4 +7,4 @@ end
|
|
|
7
7
|
|
|
8
8
|
platform :jruby do
|
|
9
9
|
gem 'activerecord-jdbcsqlite3-adapter', '>=1.3.0.beta2'
|
|
10
|
-
end
|
|
10
|
+
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
eval
|
|
1
|
+
base_gemfile = File.expand_path('../Gemfile.base', __FILE__)
|
|
2
|
+
eval File.read(base_gemfile), binding, base_gemfile
|
|
3
3
|
|
|
4
4
|
platform :ruby do
|
|
5
5
|
gem "sqlite3"
|
|
@@ -7,4 +7,4 @@ end
|
|
|
7
7
|
|
|
8
8
|
platform :jruby do
|
|
9
9
|
gem 'activerecord-jdbcsqlite3-adapter', '>=1.3.0.beta2'
|
|
10
|
-
end
|
|
10
|
+
end
|
data/lib/schema_plus/foreign_keys/active_record/connection_adapters/abstract/schema_creation.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SchemaPlus
|
|
2
4
|
module Core
|
|
3
5
|
module ActiveRecord
|
|
@@ -10,20 +12,9 @@ module SchemaPlus
|
|
|
10
12
|
# conversion of ForeignKeyDefinitions to SQL
|
|
11
13
|
o.to_sql
|
|
12
14
|
end
|
|
13
|
-
|
|
14
|
-
# The TableDefinition::foreign_keys attribute contains ForeignKeyDefinitions instead of
|
|
15
|
-
# [to_table, options] tuples when using schema_plus_foreign_keys.
|
|
16
|
-
# This function happily accepts to_table and options arguments anyway, so we just ignore
|
|
17
|
-
# all arguments and treat to_table as the ForeignKeyDefinition and convert it to SQL
|
|
18
|
-
# directly.
|
|
19
|
-
def foreign_key_in_create(from_table, to_table, options)
|
|
20
|
-
accept to_table # This is the ForeignKeyDefinition
|
|
21
|
-
end
|
|
22
|
-
|
|
23
15
|
end
|
|
24
16
|
end
|
|
25
17
|
end
|
|
26
18
|
end
|
|
27
19
|
end
|
|
28
20
|
end
|
|
29
|
-
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative 'abstract/schema_creation'
|
|
2
4
|
|
|
3
5
|
module SchemaPlus::ForeignKeys
|
|
@@ -22,27 +24,16 @@ module SchemaPlus::ForeignKeys
|
|
|
22
24
|
# constraints; they must be included in the table specification when
|
|
23
25
|
# it's created. If you're using Sqlite3, this method will raise an
|
|
24
26
|
# error.)
|
|
25
|
-
def add_foreign_key(
|
|
26
|
-
options = args.extract_options!
|
|
27
|
-
case args.length
|
|
28
|
-
when 2
|
|
29
|
-
from_table, to_table = args
|
|
30
|
-
when 4
|
|
31
|
-
ActiveSupport::Deprecation.warn "4-argument form of add_foreign_key is deprecated. use add_foreign_key(from_table, to_table, options)"
|
|
32
|
-
(from_table, column, to_table, primary_key) = args
|
|
33
|
-
options.merge!(column: column, primary_key: primary_key)
|
|
34
|
-
end
|
|
35
|
-
|
|
27
|
+
def add_foreign_key(from_table, to_table, **options) # (table_name, column, to_table, primary_key, options = {})
|
|
36
28
|
options = options.dup
|
|
37
29
|
options[:column] ||= foreign_key_column_for(to_table)
|
|
38
|
-
options[:name] ||= ForeignKeyDefinition.default_name(from_table, options[:column])
|
|
39
30
|
|
|
40
31
|
foreign_key_sql = add_foreign_key_sql(from_table, to_table, options)
|
|
41
32
|
execute "ALTER TABLE #{quote_table_name(from_table)} #{foreign_key_sql}"
|
|
42
33
|
end
|
|
43
34
|
|
|
44
35
|
# called directly by AT's bulk_change_table, for migration
|
|
45
|
-
# change_table :name, :
|
|
36
|
+
# change_table :name, bulk: true { ... }
|
|
46
37
|
def add_foreign_key_sql(from_table, to_table, options = {}) #:nodoc:
|
|
47
38
|
foreign_key = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(from_table, AbstractAdapter.proper_table_name(to_table), options)
|
|
48
39
|
"ADD #{foreign_key.to_sql}"
|
|
@@ -53,7 +44,7 @@ module SchemaPlus::ForeignKeys
|
|
|
53
44
|
end
|
|
54
45
|
|
|
55
46
|
def self.proper_table_name(name)
|
|
56
|
-
|
|
47
|
+
::ActiveRecord::Migration.new.proper_table_name(name)
|
|
57
48
|
end
|
|
58
49
|
|
|
59
50
|
# Remove a foreign key constraint
|
|
@@ -66,49 +57,18 @@ module SchemaPlus::ForeignKeys
|
|
|
66
57
|
# (NOTE: Sqlite3 does not support altering a table to remove
|
|
67
58
|
# foreign-key constraints. If you're using Sqlite3, this method will
|
|
68
59
|
# raise an error.)
|
|
69
|
-
def remove_foreign_key(
|
|
70
|
-
from_table, to_table, options = normalize_remove_foreign_key_args(*args)
|
|
60
|
+
def remove_foreign_key(from_table, to_table = nil, **options)
|
|
71
61
|
options[:column] ||= foreign_key_column_for(to_table)
|
|
72
62
|
if sql = remove_foreign_key_sql(from_table, to_table, options)
|
|
73
63
|
execute "ALTER TABLE #{quote_table_name(from_table)} #{sql}"
|
|
74
64
|
end
|
|
75
65
|
end
|
|
76
66
|
|
|
77
|
-
def normalize_remove_foreign_key_args(*args)
|
|
78
|
-
options = args.extract_options!
|
|
79
|
-
if options.has_key? :column_names
|
|
80
|
-
ActiveSupport::Deprecation.warn ":column_names option is deprecated, use :column"
|
|
81
|
-
options[:column] = options.delete(:column_names)
|
|
82
|
-
end
|
|
83
|
-
if options.has_key? :references_column_names
|
|
84
|
-
ActiveSupport::Deprecation.warn ":references_column_names option is deprecated, use :primary_key"
|
|
85
|
-
options[:primary_key] = options.delete(:references_column_names)
|
|
86
|
-
end
|
|
87
|
-
if options.has_key? :references_table_name
|
|
88
|
-
ActiveSupport::Deprecation.warn ":references_table_name option is deprecated, use :to_table"
|
|
89
|
-
options[:to_table] = options.delete(:references_table_name)
|
|
90
|
-
end
|
|
91
|
-
case args.length
|
|
92
|
-
when 1
|
|
93
|
-
from_table = args[0]
|
|
94
|
-
when 2
|
|
95
|
-
from_table, to_table = args
|
|
96
|
-
when 3, 4
|
|
97
|
-
ActiveSupport::Deprecation.warn "3- and 4-argument forms of remove_foreign_key are deprecated. use add_foreign_key(from_table, to_table, options)"
|
|
98
|
-
(from_table, column, to_table, primary_key) = args
|
|
99
|
-
options.merge!(column: column, primary_key: primary_key)
|
|
100
|
-
else
|
|
101
|
-
raise ArgumentError, "Wrong number of arguments(#{args.length}) to remove_foreign_key"
|
|
102
|
-
end
|
|
103
|
-
to_table ||= options.delete(:to_table)
|
|
104
|
-
[from_table, to_table, options]
|
|
105
|
-
end
|
|
106
|
-
|
|
107
67
|
def get_foreign_key_name(from_table, to_table, options)
|
|
108
68
|
return options[:name] if options[:name]
|
|
109
69
|
|
|
110
70
|
fks = foreign_keys(from_table)
|
|
111
|
-
if fks.detect
|
|
71
|
+
if fks.detect { |it| it.name == to_table }
|
|
112
72
|
ActiveSupport::Deprecation.warn "remove_foreign_key(table, name) is deprecated. use remove_foreign_key(table, name: name)"
|
|
113
73
|
return to_table
|
|
114
74
|
end
|
data/lib/schema_plus/foreign_keys/active_record/connection_adapters/foreign_key_definition.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'active_record/connection_adapters/abstract/schema_definitions'
|
|
3
4
|
|
|
4
5
|
module SchemaPlus::ForeignKeys
|
|
@@ -17,28 +18,7 @@ module SchemaPlus::ForeignKeys
|
|
|
17
18
|
# true
|
|
18
19
|
# :initially_deferred
|
|
19
20
|
module ForeignKeyDefinition
|
|
20
|
-
|
|
21
|
-
def column_names
|
|
22
|
-
ActiveSupport::Deprecation.warn "ForeignKeyDefinition#column_names is deprecated, use Array.wrap(column)"
|
|
23
|
-
Array.wrap(column)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def references_column_names
|
|
27
|
-
ActiveSupport::Deprecation.warn "ForeignKeyDefinition#references_column_names is deprecated, use Array.wrap(primary_key)"
|
|
28
|
-
Array.wrap(primary_key)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def references_table_name
|
|
32
|
-
ActiveSupport::Deprecation.warn "ForeignKeyDefinition#references_table_name is deprecated, use #to_table"
|
|
33
|
-
to_table
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def table_name
|
|
37
|
-
ActiveSupport::Deprecation.warn "ForeignKeyDefinition#table_name is deprecated, use #from_table"
|
|
38
|
-
from_table
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
ACTIONS = { :cascade => "CASCADE", :restrict => "RESTRICT", :nullify => "SET NULL", :set_default => "SET DEFAULT", :no_action => "NO ACTION" }.freeze
|
|
21
|
+
ACTIONS = { cascade: "CASCADE", restrict: "RESTRICT", nullify: "SET NULL", set_default: "SET DEFAULT", no_action: "NO ACTION" }.freeze
|
|
42
22
|
ACTION_LOOKUP = ACTIONS.invert.freeze
|
|
43
23
|
|
|
44
24
|
def initialize(from_table, to_table, options={})
|
|
@@ -88,7 +68,7 @@ module SchemaPlus::ForeignKeys
|
|
|
88
68
|
end
|
|
89
69
|
|
|
90
70
|
def to_sql
|
|
91
|
-
sql = name ? "CONSTRAINT #{name} " : ""
|
|
71
|
+
sql = name ? +"CONSTRAINT #{name} " : +""
|
|
92
72
|
sql << "FOREIGN KEY (#{quoted_column_names.join(", ")}) REFERENCES #{quoted_to_table} (#{quoted_primary_keys.join(", ")})"
|
|
93
73
|
sql << " ON UPDATE #{ACTIONS[on_update]}" if on_update
|
|
94
74
|
sql << " ON DELETE #{ACTIONS[on_delete]}" if on_delete
|
|
@@ -109,17 +89,6 @@ module SchemaPlus::ForeignKeys
|
|
|
109
89
|
::ActiveRecord::Base.connection.quote_table_name(to_table)
|
|
110
90
|
end
|
|
111
91
|
|
|
112
|
-
def self.default_name(from_table, column)
|
|
113
|
-
name = "fk_#{fixup_schema_name(from_table)}_#{Array.wrap(column).join('_and_')}"
|
|
114
|
-
name = name.slice(0, 27) + "_" + OpenSSL::Digest::MD5.new.hexdigest(name) if name.length > 60
|
|
115
|
-
name
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def self.fixup_schema_name(table_name)
|
|
119
|
-
# replace . with _
|
|
120
|
-
table_name.to_s.gsub(/[.]/, '_')
|
|
121
|
-
end
|
|
122
|
-
|
|
123
92
|
def match(test)
|
|
124
93
|
return false unless from_table == test.from_table
|
|
125
94
|
[:to_table, :column].reject{ |attr| test.send(attr).blank? }.all? { |attr|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module SchemaPlus::ForeignKeys
|
|
2
4
|
module ActiveRecord
|
|
3
5
|
module ConnectionAdapters
|
|
@@ -7,27 +9,24 @@ module SchemaPlus::ForeignKeys
|
|
|
7
9
|
|
|
8
10
|
#:enddoc:
|
|
9
11
|
|
|
10
|
-
def remove_column(table_name, column_name, type=nil, options
|
|
12
|
+
def remove_column(table_name, column_name, type=nil, **options)
|
|
11
13
|
foreign_keys(table_name).select { |foreign_key| Array.wrap(foreign_key.column).include?(column_name.to_s) }.each do |foreign_key|
|
|
12
14
|
remove_foreign_key(table_name, name: foreign_key.name)
|
|
13
15
|
end
|
|
14
|
-
super table_name, column_name, type, options
|
|
16
|
+
super table_name, column_name, type, **options
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
def remove_foreign_key(
|
|
18
|
-
from_table, to_table, options = normalize_remove_foreign_key_args(*args)
|
|
19
|
+
def remove_foreign_key(from_table, to_table = nil, **options)
|
|
19
20
|
if options[:if_exists]
|
|
20
21
|
foreign_key_name = get_foreign_key_name(from_table, to_table, options)
|
|
21
22
|
return if !foreign_key_name or not foreign_keys(from_table).detect{|fk| fk.name == foreign_key_name}
|
|
22
23
|
end
|
|
23
24
|
options.delete(:if_exists)
|
|
24
|
-
super from_table, to_table, options
|
|
25
|
+
super from_table, to_table, **options
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
def remove_foreign_key_sql(*args)
|
|
28
|
-
super
|
|
29
|
-
ret.sub!(/DROP CONSTRAINT/, 'DROP FOREIGN KEY') if ret
|
|
30
|
-
}
|
|
29
|
+
super&.sub(/DROP CONSTRAINT/, 'DROP FOREIGN KEY')
|
|
31
30
|
end
|
|
32
31
|
|
|
33
32
|
def foreign_keys(table_name, name = nil)
|
|
@@ -52,11 +51,11 @@ module SchemaPlus::ForeignKeys
|
|
|
52
51
|
on_update = ForeignKeyDefinition::ACTION_LOOKUP[on_update] || :restrict
|
|
53
52
|
on_delete = ForeignKeyDefinition::ACTION_LOOKUP[on_delete] || :restrict
|
|
54
53
|
|
|
55
|
-
options = { :
|
|
56
|
-
:
|
|
57
|
-
:
|
|
58
|
-
:
|
|
59
|
-
:
|
|
54
|
+
options = { name: name,
|
|
55
|
+
on_delete: on_delete,
|
|
56
|
+
on_update: on_update,
|
|
57
|
+
column: columns.gsub('`', '').split(', '),
|
|
58
|
+
primary_key: primary_keys.gsub('`', '').split(', ')
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
foreign_keys << ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
|
|
@@ -92,9 +91,9 @@ module SchemaPlus::ForeignKeys
|
|
|
92
91
|
to_table = table_namespace_prefix(to_table) + to_table
|
|
93
92
|
|
|
94
93
|
options = {
|
|
95
|
-
:
|
|
96
|
-
:
|
|
97
|
-
:
|
|
94
|
+
name: constraint_name,
|
|
95
|
+
column: columns.map { |row| row['column_name'] },
|
|
96
|
+
primary_key: columns.map { |row| row['referenced_column_name'] }
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(from_table, to_table, options)
|