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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dd82359f12e9dfcd2ee7413a727637098fa160a3
|
4
|
+
data.tar.gz: c8b86be4f354952b4f64c5681c28336b4c77153a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ac770774c777fbae496152c989b884f613148eefbcc2574a7e0359fa8f95ec34514b58329b965200aa46f3da628ae5b026104bdd6a3f75df0a9e4ea6aff360a4
|
7
|
+
data.tar.gz: fd9687b783c5204c743f9646187751b8f519f1e847326a796cb88817a1a0e79d3d6d63c71cad4b99f15545a6aa820420ea4552cf78c50d7d1e068ddf85ca99ea
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,21 @@
|
|
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
|
+
sudo: false
|
7
|
+
rvm:
|
8
|
+
- 2.1.5
|
9
|
+
gemfile:
|
10
|
+
- gemfiles/activerecord-4.2.0/Gemfile.mysql2
|
11
|
+
- gemfiles/activerecord-4.2.0/Gemfile.postgresql
|
12
|
+
- gemfiles/activerecord-4.2.0/Gemfile.sqlite3
|
13
|
+
- gemfiles/activerecord-4.2.1/Gemfile.mysql2
|
14
|
+
- gemfiles/activerecord-4.2.1/Gemfile.postgresql
|
15
|
+
- gemfiles/activerecord-4.2.1/Gemfile.sqlite3
|
16
|
+
env: POSTGRESQL_DB_USER=postgres MYSQL_DB_USER=travis
|
17
|
+
addons:
|
18
|
+
postgresql: '9.4'
|
19
|
+
before_script: bundle exec rake create_databases
|
20
|
+
after_script: bundle exec rake drop_databases
|
21
|
+
script: bundle exec rake travis
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 ronen barzel
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/schema_plus_foreign_keys.svg)](http://badge.fury.io/rb/schema_plus_foreign_keys)
|
2
|
+
[![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_plus_foreign_keys.svg)](http://travis-ci.org/SchemaPlus/schema_plus_foreign_keys)
|
3
|
+
[![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_plus_foreign_keys.svg)](https://coveralls.io/r/SchemaPlus/schema_plus_foreign_keys)
|
4
|
+
[![Dependency Status](https://gemnasium.com/lomba/schema_plus_foreign_keys.svg)](https://gemnasium.com/SchemaPlus/schema_plus_foreign_keys)
|
5
|
+
|
6
|
+
# SchemaPlus::ForeignKeys
|
7
|
+
|
8
|
+
SchemaPlus::ForeignKeys provides extended support in ActiveRecord. This includes extended support for declaraing foreign key constraints in migrations; support for deferrable constraints; support for SQLite3; cleaner schema dumps.
|
9
|
+
|
10
|
+
SchemaPlus::ForeignKeys is part of the [SchemaPlus](https://github.com/SchemaPlus/) family of Ruby on Rails ActiveRecord extension gems.
|
11
|
+
|
12
|
+
For extra convenience, see also [schema_auto_foreign_keys](https://github.com/SchemaPlus/schema_auto_foreign_keys), which creates foriegn key constraints automatically.
|
13
|
+
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
<!-- SCHEMA_DEV: TEMPLATE INSTALLATION - begin -->
|
18
|
+
<!-- These lines are auto-inserted from a schema_dev template -->
|
19
|
+
As usual:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem "schema_plus_foreign_keys" # in a Gemfile
|
23
|
+
gem.add_dependency "schema_plus_foreign_keys" # in a .gemspec
|
24
|
+
```
|
25
|
+
|
26
|
+
<!-- SCHEMA_DEV: TEMPLATE INSTALLATION - end -->
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Migrations
|
31
|
+
|
32
|
+
To declare a foreign key constraint for a column, use the `:foreign_key`
|
33
|
+
option. The same options can be used with `t.integer`, `t.references`, `t.belongs_to`, `t.foreign_key`, `change_column`, and `add_foreign_key`:
|
34
|
+
|
35
|
+
t.integer :author_id, foreign_key: true # create a foreign_key to table "authors"
|
36
|
+
t.integer :author_id, foreign_key: {} # create a foreign_key to table "authors"
|
37
|
+
t.integer :author_id, foreign_key: false # don't create a constraint (this is the default)
|
38
|
+
t.integer :author, foreign_key: true # create a foreign_key to table "authors"
|
39
|
+
|
40
|
+
t.integer :parent_id, foreign_key: true # special column parent_id defaults to referencing its own table
|
41
|
+
|
42
|
+
Specify the target table and its primary key using the `:references` and `:primary_key`:
|
43
|
+
|
44
|
+
t.integer :author_id, foreign_key: { references: :authors } # the default
|
45
|
+
t.integer :author, foreign_key: { references: :authors } # the default
|
46
|
+
t.integer :author_id, foreign_key: { references: :people } # choose table name
|
47
|
+
t.integer :author_id, foreign_key: { primary_key: :ssn] } # choose primary key
|
48
|
+
t.integer :author_id, foreign_key: { references: :people, primary_key: :ssn] } # choose both
|
49
|
+
t.integer :author_id, foreign_key: { references: [:people, :ssn] } # shortcut for both
|
50
|
+
t.integer :author_id, foreign_key: { references: nil } # same as foreign_key: false
|
51
|
+
|
52
|
+
You can also specify other attributes:
|
53
|
+
|
54
|
+
t.integer :author_id, foreign_key: { name: "my_fk" } # override default auto-generated constraint name
|
55
|
+
t.integer :author_id, foreign_key: { on_delete: :cascade }
|
56
|
+
t.integer :author_id, foreign_key: { on_update: :set_null }
|
57
|
+
t.integer :author_id, foreign_key: { deferrable: true }
|
58
|
+
t.integer :author_id, foreign_key: { deferrable: :initially_deferred }
|
59
|
+
|
60
|
+
Of course the options can be combined:
|
61
|
+
|
62
|
+
t.integer :author_id, foreign_key: { references: :people, primary_key: :ssn, name: "my_fk", on_delet: :no_action }
|
63
|
+
|
64
|
+
|
65
|
+
As a shorthand, all options except `:name` can be specified without placing
|
66
|
+
them in a `foreign_key` hash, e.g.
|
67
|
+
|
68
|
+
t.integer :author_id, on_delete: :cascade # shorthand for foreign_key: { on_delete: :cascade }
|
69
|
+
t.integer :author_id, references: :people # shorthand for foreign_key: { references: :people }
|
70
|
+
|
71
|
+
To remove a foreign key constraint, you can either change the column, specifying `foreign_key: false`, or use `migration.remove_foreign_key(table, column)`
|
72
|
+
|
73
|
+
### Introspection
|
74
|
+
|
75
|
+
To examine the foreign keys on a model, you can use:
|
76
|
+
|
77
|
+
Model.foreign_keys # foreign key constraints from this model to another
|
78
|
+
Model.reverse_foreign_keys # foreign key constraints from other models to this
|
79
|
+
|
80
|
+
(These results are cached along with other column-specific information; if you change the table definition, call `Model.reset_column_information` to clear the cache)
|
81
|
+
|
82
|
+
You can also query at the connection level (uncached):
|
83
|
+
|
84
|
+
connection.foreign_keys(table_name)
|
85
|
+
connection.reverse_foreign_keys(table_name)
|
86
|
+
|
87
|
+
These calls all return an array of ForeignKeyDefinition objects, which support these methods:
|
88
|
+
|
89
|
+
fk.from_table
|
90
|
+
fk.column
|
91
|
+
fk.to_table
|
92
|
+
fk.primary_key
|
93
|
+
fk.on_update
|
94
|
+
fk.on_delete
|
95
|
+
fk.deferrable
|
96
|
+
|
97
|
+
### Configuring Defaults
|
98
|
+
|
99
|
+
If you don't specify `on_update` and `on_delete` when creating a foreign key
|
100
|
+
constraint, they normally default to whatever the DBMS's default behavior is.
|
101
|
+
|
102
|
+
But you can also configure a global default (e.g. in a Rails initializer):
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
SchemaPlus::ForeignKey.setup do |config|
|
106
|
+
config.on_update = :cascade # default is nil, meaning use default dbms behavior
|
107
|
+
config.on_delete = :nullify # default is nil, meaning use default dbms behavior
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
Or you can configure a per-table default in a migration:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
create_table :things, foreign_key: { on_update: :set_null } do |t|
|
115
|
+
...
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
### SQLite 3 Notes
|
120
|
+
|
121
|
+
SchemaPlus::ForeignKeys supports foreign key constraints in SQLite3.
|
122
|
+
|
123
|
+
However note that SQLite3 requires you to declare the constraints as part of
|
124
|
+
the table definition, and does not allow you to add, remove, or change
|
125
|
+
constraints after the fact. Thus you'll get an exception if you try
|
126
|
+
`add_foreign_key`, `remove_foreign_key`, or `change_column` changing the
|
127
|
+
foreign key options.
|
128
|
+
|
129
|
+
|
130
|
+
### Schema Dump
|
131
|
+
|
132
|
+
For clarity (and because it's required for SQLite3), in the generated `schema_dump.rb` file, the foreign key definitions are inluded within the table definitions.
|
133
|
+
|
134
|
+
This means that the tables are output sorted that a table is
|
135
|
+
defined before others that depend on it. If, however, there are circularities in the
|
136
|
+
foreign key relations, this won't be possible; In that case some table definitions will include comments indicating a "forward reference" to a table that's farther down in the file, and the constraint will be defined once that table is defined (this can never happen with SQLite3).
|
137
|
+
|
138
|
+
|
139
|
+
## Compatibility
|
140
|
+
|
141
|
+
SchemaPlus::ForeignKeys is tested on:
|
142
|
+
|
143
|
+
<!-- SCHEMA_DEV: MATRIX - begin -->
|
144
|
+
<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->
|
145
|
+
* ruby **2.1.5** with activerecord **4.2.0**, using **mysql2**, **sqlite3** or **postgresql**
|
146
|
+
* ruby **2.1.5** with activerecord **4.2.1**, using **mysql2**, **sqlite3** or **postgresql**
|
147
|
+
|
148
|
+
<!-- SCHEMA_DEV: MATRIX - end -->
|
149
|
+
|
150
|
+
## History
|
151
|
+
|
152
|
+
* 0.1.0 - Initial release, brought over from schema_plus 1.x via 2.0.0.pre*
|
153
|
+
|
154
|
+
## Development & Testing
|
155
|
+
|
156
|
+
Are you interested in contributing to SchemaPlus::ForeignKeys? Thanks! Please follow
|
157
|
+
the standard protocol: fork, feature branch, develop, push, and issue pull
|
158
|
+
request.
|
159
|
+
|
160
|
+
Some things to know about to help you develop and test:
|
161
|
+
|
162
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - begin -->
|
163
|
+
<!-- These lines are auto-inserted from a schema_dev template -->
|
164
|
+
* **schema_dev**: SchemaPlus::ForeignKeys uses [schema_dev](https://github.com/SchemaPlus/schema_dev) to
|
165
|
+
facilitate running rspec tests on the matrix of ruby, activerecord, and database
|
166
|
+
versions that the gem supports, both locally and on
|
167
|
+
[travis-ci](http://travis-ci.org/SchemaPlus/schema_plus_foreign_keys)
|
168
|
+
|
169
|
+
To to run rspec locally on the full matrix, do:
|
170
|
+
|
171
|
+
$ schema_dev bundle install
|
172
|
+
$ schema_dev rspec
|
173
|
+
|
174
|
+
You can also run on just one configuration at a time; For info, see `schema_dev --help` or the [schema_dev](https://github.com/SchemaPlus/schema_dev) README.
|
175
|
+
|
176
|
+
The matrix of configurations is specified in `schema_dev.yml` in
|
177
|
+
the project root.
|
178
|
+
|
179
|
+
|
180
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_DEV - end -->
|
181
|
+
|
182
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - begin -->
|
183
|
+
<!-- These lines are auto-inserted from a schema_dev template -->
|
184
|
+
* **schema_plus_core**: SchemaPlus::ForeignKeys uses the SchemaPlus::Core API that
|
185
|
+
provides middleware callback stacks to make it easy to extend
|
186
|
+
ActiveRecord's behavior. If that API is missing something you need for
|
187
|
+
your contribution, please head over to
|
188
|
+
[schema_plus_core](https://github.com/SchemaPlus/schema_plus_core) and open
|
189
|
+
an issue or pull request.
|
190
|
+
|
191
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_PLUS_CORE - end -->
|
192
|
+
|
193
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - begin -->
|
194
|
+
<!-- These lines are auto-inserted from a schema_dev template -->
|
195
|
+
* **schema_monkey**: SchemaPlus::ForeignKeys is implemented as a
|
196
|
+
[schema_monkey](https://github.com/SchemaPlus/schema_monkey) client,
|
197
|
+
using [schema_monkey](https://github.com/SchemaPlus/schema_monkey)'s
|
198
|
+
convention-based protocols for extending ActiveRecord and using middleware stacks.
|
199
|
+
|
200
|
+
<!-- SCHEMA_DEV: TEMPLATE USES SCHEMA_MONKEY - end -->
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'schema_plus/core'
|
2
|
+
require 'valuable'
|
3
|
+
|
4
|
+
require_relative 'foreign_keys/version'
|
5
|
+
require_relative 'foreign_keys/active_record/base'
|
6
|
+
require_relative 'foreign_keys/active_record/connection_adapters/abstract_adapter'
|
7
|
+
require_relative 'foreign_keys/active_record/connection_adapters/table_definition'
|
8
|
+
require_relative 'foreign_keys/active_record/connection_adapters/foreign_key_definition'
|
9
|
+
require_relative 'foreign_keys/active_record/migration/command_recorder'
|
10
|
+
require_relative 'foreign_keys/middleware/dumper'
|
11
|
+
require_relative 'foreign_keys/middleware/migration'
|
12
|
+
require_relative 'foreign_keys/middleware/model'
|
13
|
+
require_relative 'foreign_keys/middleware/mysql'
|
14
|
+
require_relative 'foreign_keys/middleware/sql'
|
15
|
+
|
16
|
+
module SchemaPlus::ForeignKeys
|
17
|
+
module ActiveRecord
|
18
|
+
module ConnectionAdapters
|
19
|
+
autoload :Mysql2Adapter, 'schema_plus/foreign_keys/active_record/connection_adapters/mysql2_adapter'
|
20
|
+
autoload :PostgresqlAdapter, 'schema_plus/foreign_keys/active_record/connection_adapters/postgresql_adapter'
|
21
|
+
autoload :Sqlite3Adapter, 'schema_plus/foreign_keys/active_record/connection_adapters/sqlite3_adapter'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# This global configuation options for SchemaPlus::ForeignKeys.
|
26
|
+
# Set them in +config/initializers/schema_plus_foreign_keys.rb+ using:
|
27
|
+
#
|
28
|
+
# SchemaPlus::ForeignKeys.setup do |config|
|
29
|
+
# ...
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
class Config < Valuable
|
33
|
+
|
34
|
+
|
35
|
+
##
|
36
|
+
# :attr_accessor: on_update
|
37
|
+
#
|
38
|
+
# The default value for +:on_update+ when creating foreign key
|
39
|
+
# constraints for columns. Valid values are as described in
|
40
|
+
# ForeignKeyDefinition, or +nil+ to let the database connection use
|
41
|
+
# its own default. Default is +nil+.
|
42
|
+
has_value :on_update
|
43
|
+
|
44
|
+
##
|
45
|
+
# :attr_accessor: on_delete
|
46
|
+
#
|
47
|
+
# The default value for +:on_delete+ when creating foreign key
|
48
|
+
# constraints for columns. Valid values are as described in
|
49
|
+
# ForeignKeyDefinition, or +nil+ to let the database connection use
|
50
|
+
# its own default. Default is +nil+.
|
51
|
+
has_value :on_delete
|
52
|
+
|
53
|
+
def merge(opts)
|
54
|
+
dup.update_attributes(opts)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Returns the global configuration, i.e., the singleton instance of Config
|
60
|
+
def self.config
|
61
|
+
@config ||= Config.new
|
62
|
+
end
|
63
|
+
|
64
|
+
# Initialization block is passed a global Config instance that can be
|
65
|
+
# used to configure SchemaPlus::ForeignKeys behavior. E.g., put
|
66
|
+
# something like the following in config/initializers/schema_plus_foreign_keys.rb :
|
67
|
+
#
|
68
|
+
# SchemaPlus::ForeignKeys.setup do |config|
|
69
|
+
# config.on_update = :cascade
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
def self.setup # :yields: config
|
73
|
+
yield config
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
SchemaMonkey.register SchemaPlus::ForeignKeys
|