Рельсы и ссылочная целостность

Я хотел бы знать, возможно ли написать миграцию вместо следующего необработанного оператора 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
Другие вопросы по тегам