aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb27
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb4
-rw-r--r--activerecord/test/cases/migration/foreign_key_test.rb49
4 files changed, 85 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index cc494a7f40..294ed6d7bf 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -233,6 +233,11 @@ module ActiveRecord
false
end
+ # Does this adapter support creating foreign key constraints?
+ def supports_foreign_keys?
+ false
+ end
+
# This is meant to be implemented by the adapters that support extensions
def disable_extension(name)
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index b2aeb3a058..f09ce113d6 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -448,6 +448,33 @@ module ActiveRecord
execute "ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
end
+ def add_foreign_key(from_table, to_table, options = {})
+ foreign_key_column = options.fetch(:column)
+ referenced_column = "id"
+ foreign_key_name = foreign_key_name(from_table, options)
+ execute <<-SQL
+ALTER TABLE #{quote_table_name(from_table)}
+ADD CONSTRAINT #{foreign_key_name}
+ FOREIGN KEY (#{quote_column_name(foreign_key_column)})
+ REFERENCES #{quote_table_name(to_table)} (#{quote_column_name(referenced_column)})
+ SQL
+ end
+
+ def remove_foreign_key(from_table, options = {})
+ foreign_key_name = foreign_key_name(from_table, options)
+ execute <<-SQL
+ALTER TABLE #{quote_table_name(from_table)}
+DROP CONSTRAINT #{foreign_key_name}
+ SQL
+ end
+
+ def foreign_key_name(table_name, options)
+ options.fetch(:name) do
+ column_name = options.fetch(:column)
+ "#{table_name}_#{column_name}_fk"
+ end
+ end
+
def index_name_length
63
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index be4ae47d09..34262cf91d 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -159,6 +159,10 @@ module ActiveRecord
true
end
+ def supports_foreign_keys?
+ true
+ end
+
def index_algorithms
{ concurrently: 'CONCURRENTLY' }
end
diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb
new file mode 100644
index 0000000000..978d1a8cf1
--- /dev/null
+++ b/activerecord/test/cases/migration/foreign_key_test.rb
@@ -0,0 +1,49 @@
+require 'cases/helper'
+
+if ActiveRecord::Base.connection.supports_foreign_keys?
+module ActiveRecord
+ class Migration
+ class ForeignKeyTest < ActiveRecord::TestCase
+ class Rocket < ActiveRecord::Base
+ end
+
+ class Astronaut < ActiveRecord::Base
+ end
+
+ setup do
+ @connection = ActiveRecord::Base.connection
+ @connection.create_table "rockets" do |t|
+ t.string :name
+ end
+
+ @connection.create_table "astronauts" do |t|
+ t.string :name
+ t.references :rocket
+ end
+ end
+
+ def test_add_foreign_key
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
+
+ assert_raises ActiveRecord::InvalidForeignKey do
+ Astronaut.create rocket_id: 33
+ end
+ end
+
+ def test_remove_foreign_key
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
+ @connection.remove_foreign_key :astronauts, column: "rocket_id"
+
+ Astronaut.create rocket_id: 33
+ end
+
+ def test_remove_foreign_key_by_name
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
+ @connection.remove_foreign_key :astronauts, name: "fancy_named_fk"
+
+ Astronaut.create rocket_id: 33
+ end
+ end
+ end
+end
+end