Рельсы и ссылочная целостность
Я хотел бы знать, возможно ли написать миграцию вместо следующего необработанного оператора SQL:
execute <<-SQL
ALTER TABLE records
ADD CONSTRAINT fk_records_domains
FOREIGN KEY (domain_id)
REFERENCES domains(id) ON DELETE CASCADE
SQL
Я хотел бы избежать использования sql, потому что у меня возникают проблемы при попытке отката такой миграции:
execute <<-SQL
ALTER TABLE records
DROP FOREIGN KEY fk_records_categories
SQL
rake db:rollback
== Integrity: reverting ======================================================
-- execute(" ALTER TABLE records\n DROP FOREIGN KEY fk_records_categories\n")
rake aborted!
An error has occurred, all later migrations canceled:
Mysql2::Error: Error on rename of './BlackshardDev/records' to './BlackshardDev/#sql2-44cc-16c' (errno: 152): ALTER TABLE records
DROP FOREIGN KEY fk_records_categories
Я знаю, что activerecord может обрабатывать ссылочную целостность, но я хотел бы иметь возможность управлять ею также с помощью бэкэнда. Спасибо
2 ответа
Согласно руководству по Rails Migrations:
Способ Active Record утверждает, что интеллект принадлежит вашим моделям, а не базе данных. Таким образом, такие функции, как триггеры или ограничения внешнего ключа, которые возвращают часть этой информации обратно в базу данных, используются не интенсивно.
...
Хотя Active Record не предоставляет никаких инструментов для работы непосредственно с такими функциями, метод execute может использоваться для выполнения произвольного SQL. Вы также можете использовать некоторый плагин, такой как иностранец, который добавляет поддержку внешнего ключа в Active Record (включая поддержку для выгрузки внешних ключей в db/schema.rb).
иностранец, add_foreign_key
а также remove_foreign_key
вероятно, делай то, что ты просишь, но у меня нет прямого опыта с этим.
Для всех, кто ищет пример решения, миграция и откат работают:
def up
change_table :records do |t|
t.foreign_key :domains, :dependent => :delete
end
change_table :cryptokeys do |t|
t.foreign_key :domains, :dependent => :delete
end
change_table :domainmetadata do |t|
t.foreign_key :domains, :dependent => :delete
end
end
def down
change_table :records do |t|
t.remove_foreign_key :domains
end
change_table :cryptokeys do |t|
t.remove_foreign_key :domains
end
change_table :domainmetadata do |t|
t.remove_foreign_key :domains
end
end