From 6b9948c85e174b77b4e4e4a904c2b6fcf1083628 Mon Sep 17 00:00:00 2001 From: Rich Date: Mon, 6 Aug 2018 14:00:22 +0800 Subject: Allow `to_table` in `invert_remove_foreign_key` remove_foreign_key supports - remove_foreign_key :accounts, :branches - remove_foreign_key :accounts, to_table: :branches but the second one is not reversible. This branch is to fix and allow second one to be reversible. [Nikolay Epifanov, Rich Chen] --- activerecord/CHANGELOG.md | 4 ++++ .../connection_adapters/abstract/schema_statements.rb | 9 ++++++++- .../lib/active_record/migration/command_recorder.rb | 19 ++++++++++++++++--- .../test/cases/migration/command_recorder_test.rb | 8 ++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index d1ae41ab97..06ce2e6d4f 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -73,5 +73,9 @@ *DHH* +* Allow `to_table` in `invert_remove_foreign_key`. + + *Nikolay Epifanov*, *Rich Chen* + Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/activerecord/CHANGELOG.md) for previous changes. 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 3be0906f2a..fd9bf48ab5 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -980,11 +980,18 @@ module ActiveRecord # # remove_foreign_key :accounts, column: :owner_id # + # Removes the foreign key on +accounts.owner_id+. in a reversible manner + # + # remove_foreign_key :accounts, column: :owner_id, to_table: :owners + # # Removes the foreign key named +special_fk_name+ on the +accounts+ table. # # remove_foreign_key :accounts, name: :special_fk_name # - # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key. + # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key + # with an addition of + # [:to_table] + # The table contains the referenced primary key. def remove_foreign_key(from_table, options_or_to_table = {}) return unless supports_foreign_keys? diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index 087632b10f..dea6d4ec08 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -214,11 +214,24 @@ module ActiveRecord end def invert_remove_foreign_key(args) - from_table, to_table, remove_options = args - raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? || to_table.is_a?(Hash) + from_table, options_or_to_table, options_or_nil = args + + to_table = if options_or_to_table.is_a?(Hash) + options_or_to_table[:to_table] + else + options_or_to_table + end + + remove_options = if options_or_to_table.is_a?(Hash) + options_or_to_table.except(:to_table) + else + options_or_nil + end + + raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? reversed_args = [from_table, to_table] - reversed_args << remove_options if remove_options + reversed_args << remove_options if remove_options.present? [:add_foreign_key, reversed_args] end diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb index 3a11bb081b..daca296ade 100644 --- a/activerecord/test/cases/migration/command_recorder_test.rb +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -334,6 +334,14 @@ module ActiveRecord assert_equal [:add_foreign_key, [:dogs, :people, on_delete: :nullify, on_update: :cascade]], enable end + def test_invert_remove_foreign_key_with_to_table_in_options + enable = @recorder.inverse_of :remove_foreign_key, [:dogs, to_table: :people] + assert_equal [:add_foreign_key, [:dogs, :people]], enable + + enable = @recorder.inverse_of :remove_foreign_key, [:dogs, to_table: :people, column: :owner_id] + assert_equal [:add_foreign_key, [:dogs, :people, column: :owner_id]], enable + end + def test_invert_remove_foreign_key_is_irreversible_without_to_table assert_raises ActiveRecord::IrreversibleMigration do @recorder.inverse_of :remove_foreign_key, [:dogs, column: "owner_id"] -- cgit v1.2.3