'How do I drop a foreign key if it exists in Ruby on Rails?
There's a function called index_exists?
in ActionRecord, but no foreign_key_exists?
on Rails 4.2.7.
So when I call remove_foreign_key :parties, :franchise_groups
on some databases it breaks.
What should I use?
Update
My code
class RemoveForeignKey < ActiveRecord::Migration
def up
if foreign_key_exists?(:parties, :franchise_groups)
remove_foreign_key :parties, :franchise_groups
end
end
end
gives the error
== 20161107163800 RemoveForeignKey: migrating =================================
-- foreign_key_exists?(:parties, :franchise_groups)
rake aborted!
An error has occurred, all later migrations canceled:
undefined method `foreign_key_exists?' for #<RemoveForeignKey:0x00000007ea0b58>
/home/rje/.rvm/gems/ruby-2.3.0/gems/activerecord-4.2.7/lib/active_record/migration.rb:664:in `block in method_missing'
Solution 1:[1]
but no
foreign_key_exists?
There is foreign_key_exists?
:)
Checks to see if a foreign key exists on a table for a given foreign key definition.
# Checks to see if a foreign key exists. foreign_key_exists?(:accounts, :branches)
# Checks to see if a foreign key on a specified column exists. foreign_key_exists?(:accounts, column: :owner_id)
# Checks to see if a foreign key with a custom name exists. foreign_key_exists?(:accounts, name: "special_fk_name")
Alternatively, you can use foreign_keys
:
if foreign_keys(:table_name).include?(foreign_key_name)
# do stuff
end
Solution 2:[2]
On Rails 4 there is no foreign_key_exists so I came up with the following solution:
remove_foreign_key :events, column: :subscribers_selector_id if foreign_keys(:events).map(&:column).include?("subscribers_selector_id")
Solution 3:[3]
I think you can use something like this
def up
remove_foreign_key :parties, column: :franchise_groups
end
def down
add_foreign_key :parties, :franchise_groups
end
Solution 4:[4]
It works on connection:
ActiveRecord::Base.connection.foreign_key_exists?(:parties, :franchise_groups)
Solution 5:[5]
My Rails version doesn't seem to have "foreign_key_exists?" (Rails 4.2.6), so I'm using Array#any? to search through the results from "foreign_keys" and determine whether a given foreign key exists:
foreign_keys("parties").any?{|k| k[:to_table] == "franchise_groups"}
You can use it as such:
if foreign_keys("parties").any?{|k| k[:to_table] == "franchise_groups"}
remove_foreign_key :parties, column: :franchise_group_id
end
Solution 6:[6]
Rails 7+ if_exists / if_not_exists options
Rails 7 adds if_exists
option to remove_foreign_key
in order to not raise an error when the foreign key is already removed.
Rails 7 adds if_not_exists
option to add_foreign_key
in order to not raise an error when the foreign key is already added.
As a result, a migration can be written in the following way:
class RemoveFranchiseGroupForeignKeysFromParties < ActiveRecord::Migration
def up
remove_foreign_key :parties, :franchise_groups, if_exists: true
end
def down
add_foreign_key :parties, :franchise_groups, if_not_exists: true
end
end
Sources:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Rubycon |
Solution 3 | Deepak Mahakale |
Solution 4 | Aurel Branzeanu |
Solution 5 | |
Solution 6 | Marian13 |