From a893718c3165aa6ef6b2b500f7922954ba21eb02 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Wed, 11 Feb 2015 11:09:29 +0100 Subject: fix `remove_reference` with `foreign_key: true` on MySQL. #18664. MySQL rejects to remove an index which is used in a foreign key constraint: ``` ActiveRecord::StatementInvalid: Mysql2::Error: Cannot drop index 'index_copies_on_title_id': needed in a foreign key constraint: ALTER TABLE `copies` DROP `title_id` ``` Removing the constraint before removing the column (and the index) solves this problem. --- activerecord/CHANGELOG.md | 8 ++++++++ .../connection_adapters/abstract/schema_statements.rb | 6 ++++++ .../test/cases/migration/references_foreign_key_test.rb | 10 ++++++++++ 3 files changed, 24 insertions(+) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index c1b803c7f8..064c9008e0 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,11 @@ +* `remove_reference` with `foreign_key: true` removes the foreign key before + removing the column. This fixes a bug where it was not possible to remove + the column on MySQL. + + Fixes #18664. + + *Yves Senn* + * `find_in_batches` now accepts an `:end_at` parameter that complements the `:start` parameter to specify where to stop batch processing. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index ed32997d25..3ca1c3c49a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -662,7 +662,13 @@ module ActiveRecord # # remove_reference(:products, :supplier, polymorphic: true) # + # ====== Remove the reference with a foreign key + # + # remove_reference(:products, :user, index: true, foreign_key: true) + # def remove_reference(table_name, ref_name, options = {}) + remove_foreign_key table_name, ref_name if options[:foreign_key] + remove_column(table_name, "#{ref_name}_id") remove_column(table_name, "#{ref_name}_type") if options[:polymorphic] end diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 99de7db70c..cf1328e4d0 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -95,6 +95,16 @@ module ActiveRecord end end end + + test "foreign key column can be removed" do + @connection.create_table :testings do |t| + t.references :testing_parent, index: true, foreign_key: true + end + + assert_difference "@connection.foreign_keys('testings').size", -1 do + @connection.remove_reference :testings, :testing_parent, foreign_key: true + end + end end end end -- cgit v1.2.3