schema_plus_foreign_keys 0.1.8 → 1.0.1
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 +173 -0
- data/.gitignore +1 -0
- data/.simplecov +20 -0
- data/Gemfile +4 -1
- data/README.md +43 -27
- 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/gemfiles/activerecord-6.1/Gemfile.base +4 -0
- data/gemfiles/activerecord-6.1/Gemfile.mysql2 +10 -0
- data/gemfiles/activerecord-6.1/Gemfile.postgresql +10 -0
- data/gemfiles/{activerecord-4.2.1 → activerecord-6.1}/Gemfile.sqlite3 +3 -3
- data/gemfiles/activerecord-7.0/Gemfile.base +4 -0
- data/gemfiles/activerecord-7.0/Gemfile.mysql2 +10 -0
- data/gemfiles/activerecord-7.0/Gemfile.postgresql +10 -0
- data/gemfiles/{activerecord-4.2.6 → activerecord-7.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 +14 -12
- 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 +5 -3
- 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 -2
- data/lib/schema_plus_foreign_keys.rb +2 -0
- data/schema_dev.yml +7 -6
- data/schema_plus_foreign_keys.gemspec +9 -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 +36 -60
- data/spec/named_schemas_spec.rb +16 -14
- data/spec/schema_dumper_spec.rb +15 -15
- data/spec/spec_helper.rb +5 -4
- data/spec/support/reference.rb +3 -2
- metadata +35 -99
- 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.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-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
@@ -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)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module ActiveRecord
|
3
5
|
module ConnectionAdapters
|
@@ -61,12 +63,12 @@ module SchemaPlus::ForeignKeys
|
|
61
63
|
on_update = ForeignKeyDefinition::ACTION_LOOKUP[on_update] || :no_action
|
62
64
|
on_delete = ForeignKeyDefinition::ACTION_LOOKUP[on_delete] || :no_action
|
63
65
|
|
64
|
-
options = { :
|
65
|
-
:
|
66
|
-
:
|
67
|
-
:
|
68
|
-
:
|
69
|
-
:
|
66
|
+
options = { name: name,
|
67
|
+
on_delete: on_delete,
|
68
|
+
on_update: on_update,
|
69
|
+
column: columns,
|
70
|
+
primary_key: primary_keys,
|
71
|
+
deferrable: deferrable }
|
70
72
|
|
71
73
|
foreign_keys << ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
|
72
74
|
from_table,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module ActiveRecord
|
3
5
|
module ConnectionAdapters
|
@@ -59,12 +61,12 @@ module SchemaPlus::ForeignKeys
|
|
59
61
|
on_delete = ForeignKeyDefinition::ACTION_LOOKUP[on_delete] || :no_action
|
60
62
|
deferrable = deferrable ? (initially_deferred ? :initially_deferred : true) : false
|
61
63
|
|
62
|
-
options = { :
|
63
|
-
:
|
64
|
-
:
|
65
|
-
:
|
66
|
-
:
|
67
|
-
:
|
64
|
+
options = { name: name,
|
65
|
+
on_update: on_update,
|
66
|
+
on_delete: on_delete,
|
67
|
+
column: columns,
|
68
|
+
primary_key: primary_keys,
|
69
|
+
deferrable: deferrable }
|
68
70
|
|
69
71
|
foreign_keys << ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
|
70
72
|
from_table,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters
|
2
4
|
|
3
5
|
#
|
@@ -25,7 +27,7 @@ module SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters
|
|
25
27
|
# definition, via:
|
26
28
|
#
|
27
29
|
# create_table :widgets do |t|
|
28
|
-
# t.string :name, :
|
30
|
+
# t.string :name, index: true
|
29
31
|
# end
|
30
32
|
#
|
31
33
|
# For details about the :index option (including unique and multi-column indexes), see the
|
@@ -36,15 +38,15 @@ module SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters
|
|
36
38
|
# create_table :posts do |t| # not DRY
|
37
39
|
# t.references :author
|
38
40
|
# end
|
39
|
-
# add_foreign_key :posts, :author_id, :
|
41
|
+
# add_foreign_key :posts, :author_id, references: :authors
|
40
42
|
#
|
41
43
|
# create_table :posts do |t| # DRYer
|
42
44
|
# t.references :author
|
43
|
-
# t.foreign_key :author_id, :
|
45
|
+
# t.foreign_key :author_id, references: :authors
|
44
46
|
# end
|
45
47
|
#
|
46
48
|
# create_table :posts do |t| # Dryest
|
47
|
-
# t.references :author, :
|
49
|
+
# t.references :author, foreign_key: true
|
48
50
|
# end
|
49
51
|
#
|
50
52
|
# <b>NOTE:</b> In the standard configuration, SchemaPlus::ForeignKeys automatically
|
@@ -59,7 +61,7 @@ module SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters
|
|
59
61
|
# Finally, the configuration for foreign keys can be overriden on a per-table
|
60
62
|
# basis by passing Config options to Migration::ClassMethods#create_table, such as
|
61
63
|
#
|
62
|
-
# create_table :students, :
|
64
|
+
# create_table :students, foreign_keys: {auto_create: false} do
|
63
65
|
# t.references :student
|
64
66
|
# end
|
65
67
|
#
|
@@ -67,46 +69,5 @@ module SchemaPlus::ForeignKeys::ActiveRecord::ConnectionAdapters
|
|
67
69
|
|
68
70
|
attr_accessor :schema_plus_foreign_keys_config #:nodoc:
|
69
71
|
|
70
|
-
if Gem::Requirement.new('= 4.2.0').satisfied_by?(::ActiveRecord.version)
|
71
|
-
def foreign_keys
|
72
|
-
@foreign_keys ||= []
|
73
|
-
end
|
74
|
-
|
75
|
-
def foreign_keys_for_table(*)
|
76
|
-
foreign_keys
|
77
|
-
end
|
78
|
-
elsif Gem::Requirement.new('< 4.2.6').satisfied_by?(::ActiveRecord.version)
|
79
|
-
def foreign_keys_for_table(table)
|
80
|
-
foreign_keys[table] ||= []
|
81
|
-
end
|
82
|
-
else
|
83
|
-
def foreign_keys_for_table(*)
|
84
|
-
foreign_keys
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def foreign_key(*args) # (column_names, to_table, primary_key=nil, options=nil)
|
89
|
-
options = args.extract_options!
|
90
|
-
case args.length
|
91
|
-
when 1
|
92
|
-
to_table = args[0]
|
93
|
-
column_names = "#{to_table.to_s.singularize}_id"
|
94
|
-
when 2
|
95
|
-
column_names, to_table = args
|
96
|
-
when 3
|
97
|
-
ActiveSupport::Deprecation.warn "positional arg for foreign primary key is deprecated, use :primary_key option instead"
|
98
|
-
column_names, to_table, primary_key = args
|
99
|
-
options.merge!(:primary_key => primary_key)
|
100
|
-
else
|
101
|
-
raise ArgumentError, "wrong number of arguments (#{args.length}) for foreign_key(column_names, table_name, options)"
|
102
|
-
end
|
103
|
-
|
104
|
-
options.merge!(:column => column_names)
|
105
|
-
options.reverse_merge!(:name => ForeignKeyDefinition.default_name(self.name, column_names))
|
106
|
-
fk = ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(self.name, AbstractAdapter.proper_table_name(to_table), options)
|
107
|
-
foreign_keys_for_table(fk.to_table) << fk
|
108
|
-
self
|
109
|
-
end
|
110
|
-
|
111
72
|
end
|
112
73
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module ActiveRecord
|
3
5
|
module Migration
|
@@ -6,7 +8,7 @@ module SchemaPlus::ForeignKeys
|
|
6
8
|
attr_accessor :schema_plus_foreign_keys_config #:nodoc:
|
7
9
|
|
8
10
|
# seems like this is fixing a rails bug:
|
9
|
-
# change_table foo, :
|
11
|
+
# change_table foo, bulk: true { |t| t.references :bar }
|
10
12
|
# results in an 'unknown method :add_reference_sql' (with mysql2)
|
11
13
|
#
|
12
14
|
# should track it down separately and submit a patch/fix to rails
|
@@ -16,7 +18,7 @@ module SchemaPlus::ForeignKeys
|
|
16
18
|
options[:references] = nil if polymorphic
|
17
19
|
# ugh. copying and pasting code from ::ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference
|
18
20
|
index_options = options.delete(:index)
|
19
|
-
add_column(table_name, "#{ref_name}_id", :integer, options)
|
21
|
+
add_column(table_name, "#{ref_name}_id", :integer, **options)
|
20
22
|
add_column(table_name, "#{ref_name}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
21
23
|
add_index(table_name, polymorphic ? %w[id type].map{ |t| "#{ref_name}_#{t}" } : "#{ref_name}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
22
24
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module Middleware
|
3
5
|
module Dumper
|
@@ -14,7 +16,7 @@ module SchemaPlus::ForeignKeys
|
|
14
16
|
@inline_fks = Hash.new{ |h, k| h[k] = [] }
|
15
17
|
@backref_fks = Hash.new{ |h, k| h[k] = [] }
|
16
18
|
|
17
|
-
env.connection.
|
19
|
+
env.connection.tables.each do |table|
|
18
20
|
if (fks = env.connection.foreign_keys(table)).any?
|
19
21
|
env.dump.data.has_fks = true
|
20
22
|
@inline_fks[table] = fks
|
@@ -37,7 +39,7 @@ module SchemaPlus::ForeignKeys
|
|
37
39
|
|
38
40
|
# Ignore the foreign key dumps at the end of the schema; we'll put them in/near their tables
|
39
41
|
def after(env)
|
40
|
-
env.dump.final.reject!
|
42
|
+
env.dump.final.reject!{ |it| it =~/foreign_key/ }
|
41
43
|
end
|
42
44
|
|
43
45
|
private
|
@@ -66,7 +68,7 @@ module SchemaPlus::ForeignKeys
|
|
66
68
|
def after(env)
|
67
69
|
dumped = {}
|
68
70
|
env.table.columns.each do |column|
|
69
|
-
if (foreign_key = env.dump.data.inline_fks[env.table.name].find
|
71
|
+
if (foreign_key = env.dump.data.inline_fks[env.table.name].find { |it| it.column.to_s == column.name })
|
70
72
|
column.options[:foreign_key] = {references: foreign_key.to_table}.merge foreign_key.options_for_dump
|
71
73
|
dumped[foreign_key] = true
|
72
74
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module Middleware
|
3
5
|
module Migration
|
@@ -22,7 +24,13 @@ module SchemaPlus::ForeignKeys
|
|
22
24
|
env.connection.foreign_keys(newname).each do |fk|
|
23
25
|
begin
|
24
26
|
env.connection.remove_foreign_key(newname, name: fk.name)
|
25
|
-
env.connection.add_foreign_key(newname, fk.to_table,
|
27
|
+
env.connection.add_foreign_key(newname, fk.to_table,
|
28
|
+
column: fk.column,
|
29
|
+
primary_key: fk.primary_key,
|
30
|
+
name: fk.name.sub(/#{oldname}/, newname),
|
31
|
+
on_update: fk.on_update,
|
32
|
+
on_delete: fk.on_delete,
|
33
|
+
deferrable: fk.deferrable)
|
26
34
|
rescue NotImplementedError
|
27
35
|
# sqlite3 can't remote or add foreign keys, so just skip it
|
28
36
|
end
|
@@ -123,9 +131,9 @@ module SchemaPlus::ForeignKeys
|
|
123
131
|
references = fk_opts.delete(:references)
|
124
132
|
case env.caller
|
125
133
|
when ::ActiveRecord::ConnectionAdapters::TableDefinition
|
126
|
-
env.caller.foreign_key(
|
134
|
+
env.caller.foreign_key(references, **fk_opts)
|
127
135
|
else
|
128
|
-
env.caller.add_foreign_key(env.table_name, references, fk_opts
|
136
|
+
env.caller.add_foreign_key(env.table_name, references, **fk_opts)
|
129
137
|
end
|
130
138
|
end
|
131
139
|
|
@@ -134,6 +142,7 @@ module SchemaPlus::ForeignKeys
|
|
134
142
|
return nil if opts.nil?
|
135
143
|
return :none if opts == false
|
136
144
|
opts = {} if opts == true
|
145
|
+
opts[:column] ||= env.column_name
|
137
146
|
opts[:references] ||= default_table_name(env)
|
138
147
|
opts[:on_update] ||= config.on_update
|
139
148
|
opts[:on_delete] ||= config.on_delete
|
@@ -141,7 +150,7 @@ module SchemaPlus::ForeignKeys
|
|
141
150
|
end
|
142
151
|
|
143
152
|
def remove_foreign_key_if_exists(env)
|
144
|
-
env.caller.remove_foreign_key(env.table_name.to_s, column: env.column_name.to_s, :
|
153
|
+
env.caller.remove_foreign_key(env.table_name.to_s, column: env.column_name.to_s, if_exists: true)
|
145
154
|
end
|
146
155
|
|
147
156
|
def default_table_name(env)
|
@@ -159,4 +168,3 @@ module SchemaPlus::ForeignKeys
|
|
159
168
|
end
|
160
169
|
end
|
161
170
|
end
|
162
|
-
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module Middleware
|
3
5
|
|
@@ -6,7 +8,7 @@ module SchemaPlus::ForeignKeys
|
|
6
8
|
module DropTable
|
7
9
|
|
8
10
|
def around(env)
|
9
|
-
if
|
11
|
+
if env.options[:force] == :cascade
|
10
12
|
env.connection.reverse_foreign_keys(env.table_name).each do |foreign_key|
|
11
13
|
env.connection.remove_foreign_key(foreign_key.from_table, name: foreign_key.name)
|
12
14
|
end
|
@@ -1,23 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SchemaPlus::ForeignKeys
|
2
4
|
module Middleware
|
3
5
|
module Sql
|
4
6
|
module Table
|
5
|
-
if Gem::Requirement.new('< 5.0').satisfied_by?(::ActiveRecord.version)
|
6
|
-
def after(env)
|
7
|
-
foreign_keys = if env.table_definition.foreign_keys.is_a? Array
|
8
|
-
env.table_definition.foreign_keys
|
9
|
-
else
|
10
|
-
env.table_definition.foreign_keys.values.tap { |v| v.flatten! }
|
11
|
-
end
|
12
|
-
|
13
|
-
# create foreign key constraints inline in table definition
|
14
|
-
env.sql.body = ([env.sql.body] + foreign_keys.map(&:to_sql)).join(', ')
|
15
|
-
|
16
|
-
# prevents AR >= 4.2.1 from emitting add_foreign_key after the table
|
17
|
-
env.table_definition.foreign_keys.clear
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
7
|
module SQLite3
|
22
8
|
def before(env)
|
23
9
|
env.connection.execute('PRAGMA FOREIGN_KEYS = ON') if env.table_definition.foreign_keys.any?
|
data/schema_dev.yml
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
lib = File.expand_path('../lib', __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
6
|
require 'schema_plus/foreign_keys/version'
|
@@ -18,16 +20,14 @@ Gem::Specification.new do |gem|
|
|
18
20
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
21
|
gem.require_paths = ["lib"]
|
20
22
|
|
21
|
-
gem.
|
22
|
-
|
23
|
-
gem.add_dependency "
|
23
|
+
gem.required_ruby_version = ">= 2.5.0"
|
24
|
+
|
25
|
+
gem.add_dependency "activerecord", ">= 5.2", "< 7.1"
|
26
|
+
gem.add_dependency "schema_plus_core", "~> 3.1.0"
|
24
27
|
gem.add_dependency "valuable"
|
25
|
-
gem.add_dependency "its-it", "~> 1.2"
|
26
28
|
|
27
|
-
gem.add_development_dependency "bundler"
|
28
|
-
gem.add_development_dependency "rake", "~>
|
29
|
+
gem.add_development_dependency "bundler"
|
30
|
+
gem.add_development_dependency "rake", "~> 13.0"
|
29
31
|
gem.add_development_dependency "rspec", "~> 3.0"
|
30
|
-
gem.add_development_dependency "schema_dev", "~>
|
31
|
-
gem.add_development_dependency "simplecov"
|
32
|
-
gem.add_development_dependency "simplecov-gem-profile"
|
32
|
+
gem.add_development_dependency "schema_dev", "~> 4.2.0"
|
33
33
|
end
|